diff --git a/CHANGELOG.txt b/CHANGELOG.txt index bdbe9fc813..73e0166fd0 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,19 @@ KiCad ChangeLog 2010 Please add newer entries at the top, list the date and your name with email address. +2010-Aug-7 UPDATE Dick Hollenbeck +================================================================================ +++common + * add xnode.cpp and xnode.h which can be used to output either an XML or + S-expression document file. + * Add class STREAM_OUTPUTFORMATTER which is a richio class which can write + to any of the wxOutputStream derivatives, such as file, socket, zip, tar. + * Added netlist.keywords +++eeschema + * netform.cpp can now output S-expression OK, although I have it commented out + pending the addition of a UI for it. + + 2010-Aug-4 UPDATE Dick Hollenbeck ================================================================================ ++eeschema netform.cpp: diff --git a/common/richio.cpp b/common/richio.cpp index f8b656efc1..344da30cc3 100644 --- a/common/richio.cpp +++ b/common/richio.cpp @@ -147,18 +147,7 @@ const char* OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, const char* quote } -//--------------------------------------------------------- - -const char* STRINGFORMATTER::GetQuoteChar( const char* wrapee ) -{ - // for what we are using STRINGFORMATTER for at this time, we can return - // the nul string always. - - return ""; -// return OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, "\"" ); -} - -int STRINGFORMATTER::vprint( const char* fmt, va_list ap ) +int OUTPUTFORMATTER::vprint( const char* fmt, va_list ap ) throw( IOError ) { int ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap ); if( ret >= (int) buffer.size() ) @@ -168,13 +157,13 @@ int STRINGFORMATTER::vprint( const char* fmt, va_list ap ) } if( ret > 0 ) - mystring.append( (const char*) &buffer[0] ); + write( &buffer[0], ret ); return ret; } -int STRINGFORMATTER::sprint( const char* fmt, ... ) +int OUTPUTFORMATTER::sprint( const char* fmt, ... ) throw( IOError ) { va_list args; @@ -186,9 +175,8 @@ int STRINGFORMATTER::sprint( const char* fmt, ... ) } -int STRINGFORMATTER::Print( int nestLevel, const char* fmt, ... ) throw( IOError ) +int OUTPUTFORMATTER::Print( int nestLevel, const char* fmt, ... ) throw( IOError ) { - #define NESTWIDTH 2 ///< how many spaces per nestLevel va_list args; @@ -200,17 +188,14 @@ int STRINGFORMATTER::Print( int nestLevel, const char* fmt, ... ) throw( IOError for( int i=0; i---------------------------------------------------- + +void STRINGFORMATTER::write( const char* aOutBuf, int aCount ) throw( IOError ) +{ + mystring.append( aOutBuf, aCount ); +} + void STRINGFORMATTER::StripUseless() { std::string copy = mystring; @@ -234,3 +226,29 @@ void STRINGFORMATTER::StripUseless() } } + +//------------------------------------------- + +const char* STREAM_OUTPUTFORMATTER::GetQuoteChar( const char* wrapee ) +{ + return OUTPUTFORMATTER::GetQuoteChar( wrapee, quoteChar ); +} + + +void STREAM_OUTPUTFORMATTER::write( const char* aOutBuf, int aCount ) throw( IOError ) +{ + int lastWrite; + + // This might delay awhile if you were writing to say a socket, but for + // a file it should only go through the loop once. + for( int total = 0; totalPrint( nestLevel, "(%s", CONV_TO_UTF8( GetName() ) ); + FormatContents( out, nestLevel ); + if( GetNext() ) + out->Print( 0, ")\n" ); + else + out->Print( 0, ")" ); + break; - // output children if they exist. - - // output "contents" if it exists. Use quote need checker to wrap contents if needed. - - // A good XML element will not have both children AND contents, usually one or the other. - // children != attributes in the above statement. - -// for( XNODE*... + default: + FormatContents( out, nestLevel ); + } } void XNODE::FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { - // overridden in ELEM_HOLDER -} + std::string utf8; + const char* quote; - -void XATTR::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) -{ // output attributes first if they exist + for( XATTR* attr = (XATTR*) GetAttributes(); attr; attr = (XATTR*) attr->GetNext() ) + { + utf8 = CONV_TO_UTF8( attr->GetValue() ); // capture the content + quote = out->GetQuoteChar( utf8.c_str() ); - // output children if they exist. + out->Print( 0, " (%s %s%s%s)", + // attr names should never need quoting, no spaces, we designed the file. + CONV_TO_UTF8( attr->GetName() ), + quote, utf8.c_str(), quote ); + } - // output "contents" if it exists. Use quote need checker to wrap contents if needed. + // we only expect to have used one of two types here: + switch( GetType() ) + { + case wxXML_ELEMENT_NODE: - // A good XML element will not have both children AND contents, usually one or the other. - // children != attributes in the above statement. + // output children if they exist. + for( XNODE* kid = (XNODE*) GetChildren(); kid; kid = (XNODE*) kid->GetNext() ) + { + if( kid->GetType() != wxXML_TEXT_NODE ) + { + if( kid == GetChildren() ) + out->Print( 0, "\n" ); + kid->Format( out, nestLevel+1 ); + } + else + { + kid->Format( out, 0 ); + } + } + break; -// for( XNODE*... -} + case wxXML_TEXT_NODE: + utf8 = CONV_TO_UTF8( GetContent() ); + quote = out->GetQuoteChar( utf8.c_str() ); + out->Print( 0, " %s%s%s", quote, utf8.c_str(), quote ); + break; - -void XATTR::FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) -{ - // overridden in ELEM_HOLDER + default: + ; // not supported + } } diff --git a/eeschema/netform.cpp b/eeschema/netform.cpp index 1df1cffe97..21bd78de13 100644 --- a/eeschema/netform.cpp +++ b/eeschema/netform.cpp @@ -190,46 +190,45 @@ class EXPORT_HELP */ void writeListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ); - /** * Function makeGenericRoot * builds the entire document tree for the generic export. This is factored * out here so we can write the tree in either S-expression file format * or in XML if we put the tree built here into a wxXmlDocument. */ - XNODE* makeGenericRoot(); + XNODE* makeGenericRoot(); /** * Function makeGenericComponents * returns a sub-tree holding all the schematic components. */ - XNODE* makeGenericComponents(); + XNODE* makeGenericComponents(); /** * Function makeGenericDesignHeader * fills out a project "design" header into an XML node. - * @return XNODE* - the design header + * @return XNODE* - the design header */ - XNODE* makeGenericDesignHeader(); + XNODE* makeGenericDesignHeader(); /** * Function makeGenericLibParts * fills out an XML node with the unique library parts and returns it. */ - XNODE* makeGenericLibParts(); + XNODE* makeGenericLibParts(); /** * Function makeGenericListOfNets * fills out an XML node with a list of nets and returns it. */ - XNODE* makeGenericListOfNets(); + XNODE* makeGenericListOfNets(); /** * Function makeGenericLibraries * fills out an XML node with a list of used libraries and returns it. * Must have called makeGenericLibParts() before this function. */ - XNODE* makeGenericLibraries(); + XNODE* makeGenericLibraries(); public: @@ -392,6 +391,12 @@ static bool sortPinsByNum( NETLIST_OBJECT* aPin1, NETLIST_OBJECT* aPin2 ) return RefDesStringCompare( aPin1->GetPinNumText(), aPin2->GetPinNumText() ) < 0; } +static bool sortPinsByNumber( LIB_PIN* aPin1, LIB_PIN* aPin2 ) +{ + // return "lhs < rhs" + return RefDesStringCompare( aPin1->GetNumber(), aPin2->GetNumber() ) < 0; +} + void EXPORT_HELP::sprintPinNetName( wxString* aResult, const wxString& aNetNameFormat, NETLIST_OBJECT* aPin ) @@ -577,7 +582,7 @@ static XNODE* node( const wxString& aName, const wxString& aTextualContent = wxE XNODE* EXPORT_HELP::makeGenericDesignHeader() { - XNODE* xdesign = node( wxT("design") ); + XNODE* xdesign = node( wxT("design") ); char date[128]; DateAndTime( date ); @@ -616,17 +621,17 @@ XNODE* EXPORT_HELP::makeGenericDesignHeader() } -XNODE* EXPORT_HELP::makeGenericLibraries() +XNODE* EXPORT_HELP::makeGenericLibraries() { - XNODE* xlibs = node( wxT( "libraries" ) ); // auto_ptr + XNODE* xlibs = node( wxT( "libraries" ) ); // auto_ptr for( std::set::iterator it = m_Libraries.begin(); it!=m_Libraries.end(); ++it ) { CMP_LIBRARY* lib = (CMP_LIBRARY*) *it; - XNODE* xlibrary; + XNODE* xlibrary; xlibs->AddChild( xlibrary = node( wxT( "library" ) ) ); - xlibrary->AddProperty( wxT( "logical" ), lib->GetLogicalName() ); + xlibrary->AddAttribute( wxT( "logical" ), lib->GetLogicalName() ); xlibrary->AddChild( node( wxT( "uri" ), lib->GetFullFileName() ) ); // @todo: add more fun stuff here @@ -636,7 +641,7 @@ XNODE* EXPORT_HELP::makeGenericLibraries() } -XNODE* EXPORT_HELP::makeGenericLibParts() +XNODE* EXPORT_HELP::makeGenericLibParts() { XNODE* xlibparts = node( wxT( "libparts" ) ); // auto_ptr wxString sLibpart = wxT( "libpart" ); @@ -651,7 +656,6 @@ XNODE* EXPORT_HELP::makeGenericLibParts() wxString sDescr = wxT( "description" ); wxString sDocs = wxT( "docs" ); - LIB_PIN_LIST pinList; LIB_FIELD_LIST fieldList; @@ -666,8 +670,8 @@ XNODE* EXPORT_HELP::makeGenericLibParts() XNODE* xlibpart; xlibparts->AddChild( xlibpart = node( sLibpart ) ); - xlibpart->AddProperty( sLib, library->GetLogicalName() ); - xlibpart->AddProperty( sPart, lcomp->GetName() ); + xlibpart->AddAttribute( sLib, library->GetLogicalName() ); + xlibpart->AddAttribute( sPart, lcomp->GetName() ); //----- show the important properties ------------------------- if( !lcomp->GetDescription().IsEmpty() ) @@ -693,7 +697,7 @@ XNODE* EXPORT_HELP::makeGenericLibParts() { XNODE* xfield; xfields->AddChild( xfield = node( sField, fieldList[i].m_Text ) ); - xfield->AddProperty( sName, fieldList[i].m_Name ); + xfield->AddAttribute( sName, fieldList[i].m_Name ); } } @@ -701,7 +705,7 @@ XNODE* EXPORT_HELP::makeGenericLibParts() pinList.clear(); lcomp->GetPins( pinList, 0, 0 ); - // sort the pin list here? + sort( pinList.begin(), pinList.end(), sortPinsByNumber ); if( pinList.size() ) { @@ -713,7 +717,7 @@ XNODE* EXPORT_HELP::makeGenericLibParts() XNODE* pin; pins->AddChild( pin = node( sPin ) ); - pin->AddProperty( sNum, pinList[i]->GetNumber() ); + pin->AddAttribute( sNum, pinList[i]->GetNumber() ); // caution: construction work site here, drive slowly } @@ -724,7 +728,7 @@ XNODE* EXPORT_HELP::makeGenericLibParts() } -XNODE* EXPORT_HELP::makeGenericListOfNets() +XNODE* EXPORT_HELP::makeGenericListOfNets() { XNODE* xnets = node( wxT( "nets" ) ); // auto_ptr if exceptions ever get used. wxString netCodeTxt; @@ -796,25 +800,25 @@ XNODE* EXPORT_HELP::makeGenericListOfNets() { xnets->AddChild( xnet = node( sNet ) ); netCodeTxt.Printf( sFmtd, netCode ); - xnet->AddProperty( sCode, netCodeTxt ); - xnet->AddProperty( sName, netName ); + xnet->AddAttribute( sCode, netCodeTxt ); + xnet->AddAttribute( sName, netName ); } XNODE* xnode; xnet->AddChild( xnode = node( sNode ) ); - xnode->AddProperty( sRef, ref ); - xnode->AddProperty( sPin, nitem->GetPinNumText() ); + xnode->AddAttribute( sRef, ref ); + xnode->AddAttribute( sPin, nitem->GetPinNumText() ); } return xnets; } -XNODE* EXPORT_HELP::makeGenericRoot() +XNODE* EXPORT_HELP::makeGenericRoot() { XNODE* xroot = node( wxT( "export" ) ); - xroot->AddProperty( wxT( "version" ), wxT( "D" ) ); + xroot->AddAttribute( wxT( "version" ), wxT( "D" ) ); // add the "design" header xroot->AddChild( makeGenericDesignHeader() ); @@ -832,11 +836,11 @@ XNODE* EXPORT_HELP::makeGenericRoot() } -XNODE* EXPORT_HELP::makeGenericComponents() +XNODE* EXPORT_HELP::makeGenericComponents() { - XNODE* xcomps = node( wxT( "components" ) ); + XNODE* xcomps = node( wxT( "components" ) ); - wxString timeStamp; + wxString timeStamp; // some strings we need many times, but don't want to construct more // than once for performance. These are used within loops so the @@ -844,25 +848,25 @@ XNODE* EXPORT_HELP::makeGenericComponents() // they were in a nested scope. // these are actually constructor invocations, not assignments as it appears: - wxString sFields = wxT( "fields" ); - wxString sField = wxT( "field" ); - wxString sComponent = wxT( "comp" ); // use "part" ? - wxString sName = wxT( "name" ); - wxString sRef = wxT( "ref" ); - wxString sPins = wxT( "pins" ); - wxString sPin = wxT( "pin" ); - wxString sValue = wxT( "value" ); - wxString sSheetPath = wxT( "sheetpath" ); - wxString sFootprint = wxT( "footprint" ); - wxString sDatasheet = wxT( "datasheet" ); - wxString sTStamp = wxT( "tstamp" ); - wxString sTStamps = wxT( "tstamps" ); - wxString sTSFmt = wxT( "%8.8lX" ); // comp->m_TimeStamp - wxString sLibSource = wxT( "libsource" ); - wxString sLibPart = wxT( "libpart" ); - wxString sLib = wxT( "lib" ); - wxString sPart = wxT( "part" ); - wxString sNames = wxT( "names" ); + wxString sFields = wxT( "fields" ); + wxString sField = wxT( "field" ); + wxString sComponent = wxT( "comp" ); // use "part" ? + wxString sName = wxT( "name" ); + wxString sRef = wxT( "ref" ); + wxString sPins = wxT( "pins" ); + wxString sPin = wxT( "pin" ); + wxString sValue = wxT( "value" ); + wxString sSheetPath = wxT( "sheetpath" ); + wxString sFootprint = wxT( "footprint" ); + wxString sDatasheet = wxT( "datasheet" ); + wxString sTStamp = wxT( "tstamp" ); + wxString sTStamps = wxT( "tstamps" ); + wxString sTSFmt = wxT( "%8.8lX" ); // comp->m_TimeStamp + wxString sLibSource = wxT( "libsource" ); + wxString sLibPart = wxT( "libpart" ); + wxString sLib = wxT( "lib" ); + wxString sPart = wxT( "part" ); + wxString sNames = wxT( "names" ); m_ReferencesAlreadyFound.Clear(); @@ -882,7 +886,7 @@ XNODE* EXPORT_HELP::makeGenericComponents() schItem = comp; - XNODE* xcomp; // current component being constructed + XNODE* xcomp; // current component being constructed // Output the component's elments in order of expected access frequency. // This may not always look best, but it will allow faster execution @@ -890,7 +894,7 @@ XNODE* EXPORT_HELP::makeGenericComponents() // an element. xcomps->AddChild( xcomp = node( sComponent ) ); - xcomp->AddProperty( sRef, comp->GetRef( path ) ); + xcomp->AddAttribute( sRef, comp->GetRef( path ) ); xcomp->AddChild( node( sValue, comp->GetField( VALUE )->m_Text ) ); @@ -905,7 +909,7 @@ XNODE* EXPORT_HELP::makeGenericComponents() // container element if there are any s. if( comp->GetFieldCount() > MANDATORY_FIELDS ) { - XNODE* xfields; + XNODE* xfields; xcomp->AddChild( xfields = node( sFields ) ); for( int fldNdx = MANDATORY_FIELDS; fldNdx < comp->GetFieldCount(); ++fldNdx ) @@ -915,14 +919,14 @@ XNODE* EXPORT_HELP::makeGenericComponents() // only output a field if non empty if( !f->m_Text.IsEmpty() ) { - XNODE* xfield; + XNODE* xfield; xfields->AddChild( xfield = node( sField, f->m_Text ) ); - xfield->AddProperty( sName, f->m_Name ); + xfield->AddAttribute( sName, f->m_Name ); } } } - XNODE* xlibsource; + XNODE* xlibsource; xcomp->AddChild( xlibsource = node( sLibSource ) ); // "logical" library name, which is in anticipation of a better search @@ -930,13 +934,13 @@ XNODE* EXPORT_HELP::makeGenericComponents() // is merely the library name minus path and extension. LIB_COMPONENT* entry = CMP_LIBRARY::FindLibraryComponent( comp->m_ChipName ); if( entry ) - xlibsource->AddProperty( sLib, entry->GetLibrary()->GetLogicalName() ); - xlibsource->AddProperty( sPart, comp->m_ChipName ); + xlibsource->AddAttribute( sLib, entry->GetLibrary()->GetLogicalName() ); + xlibsource->AddAttribute( sPart, comp->m_ChipName ); - XNODE* xsheetpath; + XNODE* xsheetpath; xcomp->AddChild( xsheetpath = node( sSheetPath ) ); - xsheetpath->AddProperty( sNames, path->PathHumanReadable() ); - xsheetpath->AddProperty( sTStamps, path->Path() ); + xsheetpath->AddAttribute( sNames, path->PathHumanReadable() ); + xsheetpath->AddAttribute( sTStamps, path->Path() ); timeStamp.Printf( sTSFmt, comp->m_TimeStamp ); xcomp->AddChild( node( sTStamp, timeStamp ) ); @@ -946,10 +950,45 @@ XNODE* EXPORT_HELP::makeGenericComponents() return xcomps; } +#include // wxFFileOutputStream bool EXPORT_HELP::WriteGENERICNetList( WinEDA_SchematicFrame* frame, const wxString& aOutFileName ) { -#if 1 +#if 0 + + // this code seems to work now, for S-expression support. + + bool rc = false; + wxFFileOutputStream os( aOutFileName, wxT( "wt" ) ); + + if( !os.IsOk() ) + { + L_error: + wxString msg = _( "Failed to create file " ) + aOutFileName; + DisplayError( frame, msg ); + } + else + { + XNODE* xroot = makeGenericRoot(); + + try + { + STREAM_OUTPUTFORMATTER outputFormatter( os ); + xroot->Format( &outputFormatter, 0 ); + } + catch( IOError ioe ) + { + delete xroot; + goto L_error; + } + + delete xroot; + rc = true; + } + + return rc; + +#elif 1 // output the XML format netlist. wxXmlDocument xdoc; diff --git a/eeschema/netlist.keywords b/eeschema/netlist.keywords new file mode 100644 index 0000000000..3067b27ea6 --- /dev/null +++ b/eeschema/netlist.keywords @@ -0,0 +1,35 @@ +code +comp +components +datasheet +date +description +design +docs +export +field +fields +footprint +lib +libpart +libraries +library +libsource +name +names +net +nets +node +num +part +pin +pins +ref +sheetpath +source +tool +tstamp +tstamps +uri +value +version diff --git a/include/richio.h b/include/richio.h index 56d73fa34b..345f740f96 100644 --- a/include/richio.h +++ b/include/richio.h @@ -148,14 +148,14 @@ public: /** * Function Rewind * a wrapper to the standard function rewind. - * also clear the current line number + * also clear the current line number */ void Rewind() { rewind( fp ); lineNum = 0; } - + }; @@ -201,17 +201,43 @@ public: /** * Class OUTPUTFORMATTER - * is an interface (abstract class) used to output ASCII text in a convenient - * way. The primary interface is printf() like but with support for indentation + * is an important interface (abstract) class used to output UTF8 text in a convenient + * way. The primary interface is "printf() - like" but with support for indentation * control. The destination of the 8 bit wide text is up to the implementer. + *

+ * The implementer only has to implement the write() function, but can also optionaly + * re-implement GetQuoteChar(). + *

* If you want to output a wxString, then use CONV_TO_UTF8() on it before passing * it as an argument to Print(). *

* Since this is an abstract interface, only classes derived from this one - * will be the implementations. + * may actually be used. */ class OUTPUTFORMATTER { + std::vector buffer; + + int sprint( const char* fmt, ... ) throw( IOError ); + int vprint( const char* fmt, va_list ap ) throw( IOError ); + + +protected: + OUTPUTFORMATTER( int aReserve = 300 ) : + buffer( aReserve, '\0' ) + { + } + + + /** + * Function write + * should be coded in the interface implementation (derived) classes. + * + * @param aOutBuf is the start of a byte buffer to write. + * @param aCount tells how many bytes to write. + * @throw IOError, if there is a problem outputting, such as a full disk. + */ + virtual void write( const char* aOutBuf, int aCount ) throw( IOError ) = 0; #if defined(__GNUG__) // The GNU C++ compiler defines this @@ -238,7 +264,7 @@ public: * @return int - the number of characters output. * @throw IOError, if there is a problem outputting, such as a full disk. */ - virtual int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError ) = 0; + int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError ); /** * Function GetQuoteChar @@ -256,7 +282,10 @@ public: * @return const char* - the quote_char as a single character string, or "" * if the wrapee does not need to be wrapped. */ - virtual const char* GetQuoteChar( const char* wrapee ) = 0; + virtual const char* GetQuoteChar( const char* wrapee ) + { + return GetQuoteChar( wrapee, "\"" ); + } virtual ~OUTPUTFORMATTER() {} @@ -283,12 +312,8 @@ public: */ class STRINGFORMATTER : public OUTPUTFORMATTER { - std::vector buffer; std::string mystring; - int sprint( const char* fmt, ... ); - int vprint( const char* fmt, va_list ap ); - public: /** @@ -296,11 +321,10 @@ public: * reserves space in the buffer */ STRINGFORMATTER( int aReserve = 300 ) : - buffer( aReserve, '\0' ) + OUTPUTFORMATTER( aReserve ) { } - /** * Function Clear * clears the buffer and empties the internal string. @@ -316,16 +340,47 @@ public: */ void StripUseless(); - std::string GetString() { return mystring; } + //----------------------------------------------------- +protected: + void write( const char* aOutBuf, int aCount ) throw( IOError ); + //---------------------------------------------------- +}; + + +/** + * Class STREAM_OUTPUTFORMATTER + * implements OUTPUTFORMATTER to a wxWidgets wxOutputStream. The stream is + * neither opened nor closed by this class. + */ +class STREAM_OUTPUTFORMATTER : public OUTPUTFORMATTER +{ + wxOutputStream& os; + char quoteChar[2]; + +public: + + /** + * Constructor STREAM_OUTPUTFORMATTER + * can take any number of wxOutputStream derivations, so it can write + * to a file, socket, or zip file. + */ + STREAM_OUTPUTFORMATTER( wxOutputStream& aStream, char aQuoteChar = '"' ) : + os( aStream ) + { + quoteChar[0] = aQuoteChar; + quoteChar[1] = 0; + } //----------------------------------------------------- - int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError ); const char* GetQuoteChar( const char* wrapee ); + +protected: + void write( const char* aOutBuf, int aCount ) throw( IOError ); //---------------------------------------------------- }; diff --git a/include/xnode.h b/include/xnode.h index b77a71fae3..b93d00b58e 100644 --- a/include/xnode.h +++ b/include/xnode.h @@ -25,55 +25,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ - #include "richio.h" - +// #define WXUSINGDLL #include -// These are classes for eXporting document trees, and thus have names -// starting with X. They can export either in XML or S-expression format. - - -/** - * Class XATTR - * holds an XML or S-expression attribute/child value. It is used for eXporting - * a document tree in EITHER XML or S-expression. - */ -class XATTR : public wxXmlProperty // use wxXmlAttribute for wx >= 2.9 -{ -public: - XATTR() : - wxXmlProperty() - { - } - - XATTR( const wxString& aName, const wxString& aValue ) : - wxXmlProperty( aName, aValue ) - { - } - - - /** - * Function Format - * writes this object as UTF8 out to an OUTPUTFORMATTER as an S-expression - * @param out The formatter to write to. - * @param nestLevel A multiple of the number of spaces to preceed the output with. - * @throw IOError if a system error writing the output, such as a full disk. - */ - virtual void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ); - - - /** - * Function FormatContents - * writes the contents of object as UTF8 out to an OUTPUTFORMATTER as an S-expression - * This is the same as Format() except that the outer wrapper is not included. - * @param out The formatter to write to. - * @param nestLevel A multiple of the number of spaces to preceed the output with. - * @throw IOError if a system error writing the output, such as a full disk. - */ - virtual void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ); -}; - /** * Class XNODE @@ -88,13 +43,11 @@ public: { } - XNODE( wxXmlNodeType aType, const wxString& aName, const wxString& aContent = wxEmptyString ) : wxXmlNode( NULL, aType, aName, aContent ) { } - /** * Function Format * writes this object as UTF8 out to an OUTPUTFORMATTER as an S-expression @@ -104,7 +57,6 @@ public: */ virtual void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ); - /** * Function FormatContents * writes the contents of object as UTF8 out to an OUTPUTFORMATTER as an S-expression diff --git a/pcbnew/specctra.cpp b/pcbnew/specctra.cpp index 13b52b618e..73644d8257 100644 --- a/pcbnew/specctra.cpp +++ b/pcbnew/specctra.cpp @@ -52,7 +52,9 @@ #include "specctra.h" -#include +//#include +#include // wxFFileOutputStream + #include "build_version.h" @@ -3850,81 +3852,42 @@ void SPECCTRA_DB::doSUPPLY_PIN( SUPPLY_PIN* growth ) throw( IOError ) } -int SPECCTRA_DB::Print( int nestLevel, const char* fmt, ... ) throw( IOError ) -{ - va_list args; - - va_start( args, fmt ); - - int result = 0; - int total = 0; - - for( int i=0; ipcbname = CONV_TO_UTF8(filename); - pcb->Format( this, 0 ); + pcb->Format( &outputFormatter, 0 ); } - - // if an exception is thrown by Format, then ~SPECCTRA_DB() will close - // the file. - - fclose( fp ); - fp = 0; } void SPECCTRA_DB::ExportSESSION( wxString filename ) { - fp = wxFopen( filename, wxT("w") ); - - if( !fp ) - { - ThrowIOError( _("Unable to open file \"%s\""), GetChars(filename) ); - } - if( session ) - session->Format( this, 0 ); + { + wxFFileOutputStream os( filename, wxT( "wt" ) ); - fclose( fp ); - fp = 0; + if( !os.IsOk() ) + { + ThrowIOError( _("Unable to open file \"%s\""), GetChars(filename) ); + } + + STREAM_OUTPUTFORMATTER outputFormatter( os, quote_char[0] ); + + session->Format( &outputFormatter, 0 ); + } } diff --git a/pcbnew/specctra.h b/pcbnew/specctra.h index 4b27d03988..8d7ddcf6bd 100644 --- a/pcbnew/specctra.h +++ b/pcbnew/specctra.h @@ -3970,7 +3970,7 @@ typedef boost::ptr_set PADSTACKSET; * Class SPECCTRA_DB * holds a DSN data tree, usually coming from a DSN file. */ -class SPECCTRA_DB : public OUTPUTFORMATTER +class SPECCTRA_DB { /// specctra DSN keywords static const KEYWORD keywords[]; @@ -3979,13 +3979,8 @@ class SPECCTRA_DB : public OUTPUTFORMATTER DSNLEXER* lexer; PCB* pcb; - SESSION* session; - - FILE* fp; - wxString filename; - std::string quote_char; bool modulesAreFlipped; @@ -4304,7 +4299,6 @@ public: lexer = 0; pcb = 0; session = 0; - fp = 0; quote_char += '"'; modulesAreFlipped = false; } @@ -4316,18 +4310,8 @@ public: delete session; deleteNETs(); - - if( fp ) - fclose( fp ); } - - //------------------------------------------------------ - int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError ); - - const char* GetQuoteChar( const char* wrapee ); - //----------------------------------------------------- - static const char* TokenName( int aToken ); @@ -4354,11 +4338,6 @@ public: } PCB* GetPCB() { return pcb; } - void SetFILE( FILE* aFile ) - { - fp = aFile; - } - /** * Function SetSESSION * deletes any existing SESSION and replaces it with the given one.