From d8b60a14e18987c0c2ddfd408f183342fa6b5488 Mon Sep 17 00:00:00 2001
From: Wayne Stambaugh <stambaughw@verizon.net>
Date: Sun, 22 Apr 2012 11:16:39 -0400
Subject: [PATCH] Pcbnew s-expression file format improvements.

* Move board item object Format() functions into PCB_IO object.
* Change file format to use layer names instead of numbers.
* Change file extension to kicad_pcb.
---
 common/base_struct.cpp             |   8 -
 common/eda_text.cpp                |  10 -
 common/wildcards_and_files_ext.cpp |   2 +-
 include/base_struct.h              |  12 -
 pcbnew/class_board.cpp             | 195 ------
 pcbnew/class_board.h               |   3 -
 pcbnew/class_dimension.cpp         |  55 --
 pcbnew/class_dimension.h           |   3 -
 pcbnew/class_drawsegment.cpp       |  64 --
 pcbnew/class_drawsegment.h         |   3 -
 pcbnew/class_edge_mod.cpp          |  10 -
 pcbnew/class_edge_mod.h            |   3 -
 pcbnew/class_mire.cpp              |  20 -
 pcbnew/class_mire.h                |   3 -
 pcbnew/class_module.cpp            | 119 ----
 pcbnew/class_module.h              |   3 -
 pcbnew/class_pad.cpp               |  95 ---
 pcbnew/class_pad.h                 |   3 -
 pcbnew/class_pcb_text.cpp          |  16 -
 pcbnew/class_pcb_text.h            |   3 -
 pcbnew/class_text_mod.cpp          |  20 -
 pcbnew/class_text_mod.h            |   3 -
 pcbnew/class_track.cpp             |  41 --
 pcbnew/class_track.h               |   3 -
 pcbnew/class_zone.cpp              | 142 -----
 pcbnew/class_zone.h                |   3 -
 pcbnew/io_mgr.cpp                  |   2 +-
 pcbnew/kicad_plugin.cpp            | 966 ++++++++++++++++++++++++++++-
 pcbnew/kicad_plugin.h              |  72 ++-
 29 files changed, 1035 insertions(+), 847 deletions(-)

diff --git a/common/base_struct.cpp b/common/base_struct.cpp
index c6c9e74fd7..c108c37689 100644
--- a/common/base_struct.cpp
+++ b/common/base_struct.cpp
@@ -222,14 +222,6 @@ EDA_ITEM& EDA_ITEM::operator=( const EDA_ITEM& aItem )
 }
 
 
-void EDA_ITEM::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-    throw( IO_ERROR )
-{
-    wxFAIL_MSG( wxString::Format( wxT( "Format method not defined for item type %s." ),
-                                  GetChars( GetClass() ) ) );
-}
-
-
 #if defined(DEBUG)
 
 // A function that should have been in wxWidgets
diff --git a/common/eda_text.cpp b/common/eda_text.cpp
index 5d718d82f0..546a5deecf 100644
--- a/common/eda_text.cpp
+++ b/common/eda_text.cpp
@@ -346,14 +346,6 @@ bool EDA_TEXT::IsDefaultFormatting() const
 void EDA_TEXT::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
     throw( IO_ERROR )
 {
-    aFormatter->Print( aNestLevel, "(text %s (at %s",
-                       aFormatter->Quotew( m_Text ).c_str(), FMT_IU( m_Pos ).c_str() );
-
-    if( m_Orient != 0.0 )
-        aFormatter->Print( 0, " %s", FMT_ANGLE( m_Orient ).c_str() );
-
-    aFormatter->Print( 0, ")\n" );
-
     if( !IsDefaultFormatting() )
     {
         aFormatter->Print( aNestLevel+1, "(effects\n" );
@@ -400,6 +392,4 @@ void EDA_TEXT::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControl
 
         aFormatter->Print( aNestLevel+1, ")\n" );
     }
-
-    aFormatter->Print( aNestLevel, ")\n" );
 }
diff --git a/common/wildcards_and_files_ext.cpp b/common/wildcards_and_files_ext.cpp
index 6c50f1df52..0edffe7d64 100644
--- a/common/wildcards_and_files_ext.cpp
+++ b/common/wildcards_and_files_ext.cpp
@@ -55,7 +55,7 @@ const wxString SchematicFileWildcard( _( "KiCad schematic files (*.sch)|*.sch" )
 const wxString NetlistFileWildcard( _( "KiCad netlist files (*.net)|*.net" ) );
 const wxString GerberFileWildcard( _( "Gerber files (*.pho)|*.pho" ) );
 const wxString LegacyPcbFileWildcard( _( "KiCad printed circuit board files (*.brd)|*.brd" ) );
-const wxString PcbFileWildcard( _( "KiCad s-expr printed circuit board files (*.kicad_brd)|*.kicad_brd" ) );
+const wxString PcbFileWildcard( _( "KiCad s-expr printed circuit board files (*.kicad_pcb)|*.kicad_pcb" ) );
 const wxString FootprintLibFileWildcard( _( "KiCad footprint library file (*.mod)|*.mod" ) );
 const wxString PdfFileWildcard( _( "Portable document format files (*.pdf)|*.pdf" ) );
 const wxString MacrosFileWildcard( _( "KiCad recorded macros (*.mcr)|*.mcr" ) );
diff --git a/include/base_struct.h b/include/base_struct.h
index 0e9b5036fb..9350085124 100644
--- a/include/base_struct.h
+++ b/include/base_struct.h
@@ -729,18 +729,6 @@ public:
      */
     virtual EDA_ITEM& operator=( const EDA_ITEM& aItem );
 
-    /**
-     * Function Format
-     * outputs the object to \a aFormatter in s-expression form.
-     *
-     * @param aFormatter The #OUTPUTFORMATTER object to write to.
-     * @param aNestLevel The indentation next level.
-     * @param aControlBits The control bit definition for object specific formatting.
-     * @throw IO_ERROR on write error.
-     */
-    virtual void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-        throw( IO_ERROR );
-
 #if defined(DEBUG)
 
     /**
diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp
index 209afd0e5b..38f8d95828 100644
--- a/pcbnew/class_board.cpp
+++ b/pcbnew/class_board.cpp
@@ -2142,201 +2142,6 @@ TRACK* BOARD::CreateLockPoint( wxPoint& aPosition, TRACK* aSegment, PICKED_ITEMS
 }
 
 
-void BOARD::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-    throw( IO_ERROR )
-{
-    aFormatter->Print( aNestLevel, "(general\n" );
-    aFormatter->Print( aNestLevel+1, "(links %d)\n", GetRatsnestsCount() );
-    aFormatter->Print( aNestLevel+1, "(no_connects %d)\n", m_NbNoconnect );
-
-    // Write Bounding box info
-    aFormatter->Print( aNestLevel+1,  "(area %s %s %s %s)\n",
-                       FMT_IU( m_BoundingBox.GetX() ).c_str(),
-                       FMT_IU( m_BoundingBox.GetY() ).c_str(),
-                       FMT_IU( m_BoundingBox.GetRight() ).c_str(),
-                       FMT_IU( m_BoundingBox.GetBottom() ).c_str() );
-    aFormatter->Print( aNestLevel+1, "(thickness %s)\n",
-                       FMT_IU( GetDesignSettings().m_BoardThickness ).c_str() );
-
-    aFormatter->Print( aNestLevel+1, "(drawings %d)\n", m_Drawings.GetCount() );
-    aFormatter->Print( aNestLevel+1, "(tracks %d)\n", GetNumSegmTrack() );
-    aFormatter->Print( aNestLevel+1, "(zones %d)\n", GetNumSegmZone() );
-    aFormatter->Print( aNestLevel+1, "(modules %d)\n", m_Modules.GetCount() );
-    aFormatter->Print( aNestLevel+1, "(nets %d)\n", GetNetCount() );
-    aFormatter->Print( aNestLevel, ")\n\n" );
-
-    m_paper.Format( aFormatter, aNestLevel, aControlBits );
-    m_titles.Format( aFormatter, aNestLevel, aControlBits );
-
-    // Layers.
-    aFormatter->Print( aNestLevel, "(layers %d %08X", GetCopperLayerCount(), GetEnabledLayers() );
-
-    if( GetEnabledLayers() != GetVisibleLayers() )
-        aFormatter->Print( 0, " %08X", GetVisibleLayers() );
-
-    aFormatter->Print( 0, "\n" );
-
-    unsigned layerMask = ALL_CU_LAYERS & GetEnabledLayers();
-
-    for( int layer = 0;  layerMask;  ++layer, layerMask >>= 1 )
-    {
-        if( layerMask & 1 )
-        {
-            aFormatter->Print( aNestLevel+1, "(layer%d %s %s)\n", layer,
-                               TO_UTF8( GetLayerName( layer ) ),
-                               LAYER::ShowType( GetLayerType( layer ) ) );
-        }
-    }
-
-    aFormatter->Print( aNestLevel, ")\n\n" );
-
-    // Setup
-    aFormatter->Print( aNestLevel, "(setup\n" );
-
-    // Save current default track width, for compatibility with older Pcbnew version;
-    aFormatter->Print( aNestLevel+1, "(last_trace_width %s)\n",
-                       FMT_IU( m_TrackWidthList[m_TrackWidthSelector] ).c_str() );
-
-    // Save custom tracks width list (the first is not saved here: this is the netclass value
-    for( unsigned ii = 1; ii < m_TrackWidthList.size(); ii++ )
-        aFormatter->Print( aNestLevel+1, "(user_trace_width%d %s)\n",
-                           ii+1, FMT_IU( m_TrackWidthList[ii] ).c_str() );
-
-    aFormatter->Print( aNestLevel+1, "(trace_clearance %s)\n",
-                       FMT_IU( m_NetClasses.GetDefault()->GetClearance() ).c_str() );
-
-    // ZONE_SETTINGS
-    aFormatter->Print( aNestLevel+1, "(zone_clearance %s)\n",
-                       FMT_IU( GetZoneSettings().m_ZoneClearance ).c_str() );
-    aFormatter->Print( aNestLevel+1, "(zone_45_only %d)\n", GetZoneSettings().m_Zone_45_Only );
-
-    aFormatter->Print( aNestLevel+1, "(trace_min %s)\n",
-                       FMT_IU( GetDesignSettings().m_TrackMinWidth ).c_str() );
-
-    aFormatter->Print( aNestLevel+1, "(segment_width %s)\n",
-                       FMT_IU( GetDesignSettings().m_DrawSegmentWidth ).c_str() );
-    aFormatter->Print( aNestLevel+1, "(edge_width %s)\n",
-                       FMT_IU( GetDesignSettings().m_EdgeSegmentWidth ).c_str() );
-
-    // Save current default via size, for compatibility with older Pcbnew version;
-    aFormatter->Print( aNestLevel+1, "(via_size %s)\n",
-                       FMT_IU( m_NetClasses.GetDefault()->GetViaDiameter() ).c_str() );
-    aFormatter->Print( aNestLevel+1, "(via_drill %s)\n",
-                       FMT_IU( m_NetClasses.GetDefault()->GetViaDrill() ).c_str() );
-    aFormatter->Print( aNestLevel+1, "(via_min_size %s)\n",
-                       FMT_IU( GetDesignSettings().m_ViasMinSize ).c_str() );
-    aFormatter->Print( aNestLevel+1, "(via_min_drill %s)\n",
-                       FMT_IU( GetDesignSettings().m_ViasMinDrill ).c_str() );
-
-    // Save custom vias diameters list (the first is not saved here: this is
-    // the netclass value
-    for( unsigned ii = 1; ii < m_ViasDimensionsList.size(); ii++ )
-        aFormatter->Print( aNestLevel+1, "(user_via%d %s %s)\n", ii,
-                           FMT_IU( m_ViasDimensionsList[ii].m_Diameter ).c_str(),
-                           FMT_IU( m_ViasDimensionsList[ii].m_Drill ).c_str() );
-
-    // for old versions compatibility:
-    aFormatter->Print( aNestLevel+1, "(uvia_size %s)\n",
-                       FMT_IU( m_NetClasses.GetDefault()->GetuViaDiameter() ).c_str() );
-    aFormatter->Print( aNestLevel+1, "(uvia_drill %s)\n",
-                       FMT_IU( m_NetClasses.GetDefault()->GetuViaDrill() ).c_str() );
-    aFormatter->Print( aNestLevel+1, "(uvias_allow %s)\n",
-                       FMT_IU( GetDesignSettings().m_MicroViasAllowed ).c_str() );
-    aFormatter->Print( aNestLevel+1, "(uvia_min_size %s)\n",
-                       FMT_IU( GetDesignSettings().m_MicroViasMinSize ).c_str() );
-    aFormatter->Print( aNestLevel+1, "(uvia_min_drill %s)\n",
-                       FMT_IU( GetDesignSettings().m_MicroViasMinDrill ).c_str() );
-
-    aFormatter->Print( aNestLevel+1, "(pcb_text_width %s)\n",
-                       FMT_IU( GetDesignSettings().m_PcbTextWidth ).c_str() );
-    aFormatter->Print( aNestLevel+1, "(pcb_text_size %s %s)\n",
-                       FMT_IU( GetDesignSettings().m_PcbTextSize.x ).c_str(),
-                       FMT_IU( GetDesignSettings().m_PcbTextSize.y ).c_str() );
-
-    aFormatter->Print( aNestLevel+1, "(mod_edge_width %s)\n",
-                       FMT_IU( GetDesignSettings().m_ModuleSegmentWidth ).c_str() );
-    aFormatter->Print( aNestLevel+1, "(mod_text_size %s %s)\n",
-                       FMT_IU( GetDesignSettings().m_ModuleTextSize.x ).c_str(),
-                       FMT_IU( GetDesignSettings().m_ModuleTextSize.y ).c_str() );
-    aFormatter->Print( aNestLevel+1, "(mod_text_width %s)\n",
-                       FMT_IU( GetDesignSettings().m_ModuleTextWidth ).c_str() );
-
-    aFormatter->Print( aNestLevel+1, "(pad_size %s %s)\n",
-                       FMT_IU( GetDesignSettings().m_Pad_Master.GetSize().x ).c_str(),
-                       FMT_IU( GetDesignSettings().m_Pad_Master.GetSize().x ).c_str() );
-    aFormatter->Print( aNestLevel+1, "(pad_drill %s)\n",
-                       FMT_IU( GetDesignSettings().m_Pad_Master.GetDrillSize().x ).c_str() );
-
-    aFormatter->Print( aNestLevel+1, "(pad_to_mask_clearance %s)\n",
-                       FMT_IU( GetDesignSettings().m_SolderMaskMargin ).c_str() );
-
-    if( GetDesignSettings().m_SolderPasteMargin != 0 )
-        aFormatter->Print( aNestLevel+1, "(pad_to_paste_clearance %s)\n",
-                           FMT_IU( GetDesignSettings().m_SolderPasteMargin ).c_str() );
-
-    if( GetDesignSettings().m_SolderPasteMarginRatio != 0 )
-        aFormatter->Print( aNestLevel+1, "(pad_to_paste_clearance_ratio %g)\n",
-                           GetDesignSettings().m_SolderPasteMarginRatio );
-
-    aFormatter->Print( aNestLevel+1, "(aux_axis_origin %s %s)\n",
-                       FMT_IU( GetOriginAxisPosition().x ).c_str(),
-                       FMT_IU( GetOriginAxisPosition().y ).c_str() );
-
-    aFormatter->Print( aNestLevel+1, "(visible_elements %X)\n",
-                       GetDesignSettings().GetVisibleElements() );
-
-    aFormatter->Print( aNestLevel, ")\n\n" );
-
-
-    int netcount = GetNetCount();
-
-    for( int i = 0;  i < netcount;  ++i )
-        aFormatter->Print( aNestLevel, "(net %d %s)\n",
-                           FindNet( i )->GetNet(),
-                           aFormatter->Quotew( FindNet( i )->GetNetname() ).c_str() );
-
-    aFormatter->Print( 0, "\n" );
-
-    // Save the default net class first.
-    m_NetClasses.GetDefault()->Format( aFormatter, aNestLevel, aControlBits );
-
-    // Save the rest of the net classes alphabetically.
-    for( NETCLASSES::const_iterator it = m_NetClasses.begin();  it != m_NetClasses.end();  ++it )
-    {
-        NETCLASS* netclass = it->second;
-        netclass->Format( aFormatter, aNestLevel, aControlBits );
-    }
-
-    // Save the graphical items on the board (not owned by a module)
-    for( BOARD_ITEM* item = m_Drawings;  item;  item = item->Next() )
-        item->Format( aFormatter, aNestLevel, aControlBits );
-
-    aFormatter->Print( 0, "\n" );
-
-    // Save the modules.
-    for( MODULE* module = m_Modules;  module;  module = (MODULE*) module->Next() )
-    {
-        module->Format( aFormatter, aNestLevel, aControlBits );
-        aFormatter->Print( 0, "\n" );
-    }
-
-    // Do not save MARKER_PCBs, they can be regenerated easily.
-
-    // Save the tracks and vias.
-    for( TRACK* track = m_Track;  track; track = track->Next() )
-        track->Format( aFormatter, aNestLevel, aControlBits );
-
-    /// @todo Add warning here that the old segment filed zones are no longer supported and
-    ///       will not be saved.
-
-    aFormatter->Print( 0, "\n" );
-
-    // Save the polygon (which are the newer technology) zones.
-    for( int i=0;  i < GetAreaCount();  ++i )
-        GetArea( i )->Format( aFormatter, aNestLevel, aControlBits );
-}
-
-
 #if defined(DEBUG)
 
 void BOARD::Show( int nestLevel, std::ostream& os ) const
diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h
index bb13240a5f..92e8a7638c 100644
--- a/pcbnew/class_board.h
+++ b/pcbnew/class_board.h
@@ -897,9 +897,6 @@ public:
         return wxT( "BOARD" );
     }
 
-    void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-        throw( IO_ERROR );
-
 #if defined(DEBUG)
     void Show( int nestLevel, std::ostream& os ) const;     // overload
 #endif
diff --git a/pcbnew/class_dimension.cpp b/pcbnew/class_dimension.cpp
index f72805bad3..51af0595ed 100644
--- a/pcbnew/class_dimension.cpp
+++ b/pcbnew/class_dimension.cpp
@@ -605,58 +605,3 @@ EDA_ITEM* DIMENSION::Clone() const
 {
     return new DIMENSION( *this );
 }
-
-
-void DIMENSION::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-    throw( IO_ERROR )
-{
-    aFormatter->Print( aNestLevel, "(dimension %s\n", FMT_IU( m_Value ).c_str() );
-    aFormatter->Print( aNestLevel+1, "(width %s)\n(layer %d)\n(tstamp %lX)\n",
-                       FMT_IU( m_Width ).c_str(), GetLayer(), GetTimeStamp() );
-
-    m_Text.EDA_TEXT::Format( aFormatter, aNestLevel+1, aControlBits );
-
-    aFormatter->Print( aNestLevel+1, "(feature1 pts((xy %s %s) (xy %s %s)))\n",
-                       FMT_IU( m_featureLineDOx ).c_str(),
-                       FMT_IU( m_featureLineDOy ).c_str(),
-                       FMT_IU( m_featureLineDFx ).c_str(),
-                       FMT_IU( m_featureLineDFy ).c_str() );
-
-    aFormatter->Print( aNestLevel+1, "(feature2 pts((xy %s %s) (xy %s %s)))\n",
-                       FMT_IU( m_featureLineGOx ).c_str(),
-                       FMT_IU( m_featureLineGOy ).c_str(),
-                       FMT_IU( m_featureLineGFx ).c_str(),
-                       FMT_IU( m_featureLineGFy ).c_str() );
-
-    aFormatter->Print( aNestLevel+1, "(crossbar pts((xy %s %s) (xy %s %s)))\n",
-                       FMT_IU( m_crossBarOx ).c_str(),
-                       FMT_IU( m_crossBarOy ).c_str(),
-                       FMT_IU( m_crossBarFx ).c_str(),
-                       FMT_IU( m_crossBarFy ).c_str() );
-
-    aFormatter->Print( aNestLevel+1, "(arrow1a pts((xy %s %s) (xy %s %s)))\n",
-                       FMT_IU( m_arrowD1Ox ).c_str(),
-                       FMT_IU( m_arrowD1Oy ).c_str(),
-                       FMT_IU( m_arrowD1Fx ).c_str(),
-                       FMT_IU( m_arrowD1Fy ).c_str() );
-
-    aFormatter->Print( aNestLevel+1, "(arrow1b pts((xy %s %s) (xy %s %s)))\n",
-                       FMT_IU( m_arrowD2Ox ).c_str(),
-                       FMT_IU( m_arrowD2Oy ).c_str(),
-                       FMT_IU( m_arrowD2Fx ).c_str(),
-                       FMT_IU( m_arrowD2Fy ).c_str() );
-
-    aFormatter->Print( aNestLevel+1, "(arrow2a pts((xy %s %s) (xy %s %s)))\n",
-                       FMT_IU( m_arrowG1Ox ).c_str(),
-                       FMT_IU( m_arrowG1Oy ).c_str(),
-                       FMT_IU( m_arrowG1Fx ).c_str(),
-                       FMT_IU( m_arrowG1Fy ).c_str() );
-
-    aFormatter->Print( aNestLevel+1, "(arrow2b pts((xy %s %s) (xy %s %s)))\n",
-                       FMT_IU( m_arrowG2Ox ).c_str(),
-                       FMT_IU( m_arrowG2Oy ).c_str(),
-                       FMT_IU( m_arrowG2Fx ).c_str(),
-                       FMT_IU( m_arrowG2Fy ).c_str() );
-
-    aFormatter->Print( aNestLevel, ")\n" );
-}
diff --git a/pcbnew/class_dimension.h b/pcbnew/class_dimension.h
index 249cfd748b..e10b925f83 100644
--- a/pcbnew/class_dimension.h
+++ b/pcbnew/class_dimension.h
@@ -134,9 +134,6 @@ public:
 
     EDA_ITEM* Clone() const;
 
-    void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-        throw( IO_ERROR );
-
 #if defined(DEBUG)
     void Show( int nestLevel, std::ostream& os ) const { ShowDummy( os ); } // override
 #endif
diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp
index 9ec6f74941..0679b53ab4 100644
--- a/pcbnew/class_drawsegment.cpp
+++ b/pcbnew/class_drawsegment.cpp
@@ -544,70 +544,6 @@ EDA_ITEM* DRAWSEGMENT::Clone() const
 }
 
 
-void DRAWSEGMENT::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-    throw( IO_ERROR )
-{
-    unsigned i;
-
-    aFormatter->Print( aNestLevel, "(draw " );
-
-    switch( m_Shape )
-    {
-    case S_SEGMENT:  // Line
-        aFormatter->Print( 0, "line (pts (xy %s) (xy %s))",
-                           FMT_IU( m_Start ).c_str(),
-                           FMT_IU( m_End ).c_str() );
-        break;
-
-    case S_CIRCLE:  // Circle
-        aFormatter->Print( 0, "circle (center (xy %s)) (end (xy %s))",
-                           FMT_IU( m_Start ).c_str(),
-                           FMT_IU( m_End ).c_str() );
-        break;
-
-    case S_ARC:     // Arc
-        aFormatter->Print( 0, "arc (start (xy %s)) (end (xy %s)) (angle %s)",
-                           FMT_IU( m_Start ).c_str(),
-                           FMT_IU( m_End ).c_str(),
-                           FMT_ANGLE( m_Angle ).c_str() );
-        break;
-
-    case S_POLYGON: // Polygon
-        aFormatter->Print( 0, "line (pts" );
-
-        for( i = 0;  i<m_PolyPoints.size();  ++i )
-            aFormatter->Print( 0, " (xy %s)", FMT_IU( m_PolyPoints[i] ).c_str() );
-
-        aFormatter->Print( 0, ")" );
-        break;
-
-    case S_CURVE:   // Bezier curve
-        aFormatter->Print( 0, "curve pts(xy(%s) xy(%s) xy(%s) xy(%s))",
-                           FMT_IU( m_Start ).c_str(),
-                           FMT_IU( m_BezierC1 ).c_str(),
-                           FMT_IU( m_BezierC2 ).c_str(),
-                           FMT_IU( m_End ).c_str() );
-        break;
-
-    default:
-        wxFAIL_MSG( wxT( "Cannot format invalid DRAWSEGMENT type." ) );
-    };
-
-    aFormatter->Print( 0, " (layer %d)", GetLayer() );
-
-    if( m_Width != 0 )
-        aFormatter->Print( 0, " (width %s)", FMT_IU( m_Width ).c_str() );
-
-    if( GetTimeStamp() )
-        aFormatter->Print( 0, " (tstamp %lX)", GetTimeStamp() );
-
-    if( GetStatus() )
-        aFormatter->Print( 0, " (status %X)", GetStatus() );
-
-    aFormatter->Print( 0, ")\n" );
-}
-
-
 #if defined(DEBUG)
 void DRAWSEGMENT::Show( int nestLevel, std::ostream& os ) const
 {
diff --git a/pcbnew/class_drawsegment.h b/pcbnew/class_drawsegment.h
index 7d9e5e5609..d44a63146c 100644
--- a/pcbnew/class_drawsegment.h
+++ b/pcbnew/class_drawsegment.h
@@ -215,9 +215,6 @@ public:
 
     virtual EDA_ITEM* Clone() const;
 
-    virtual void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-        throw( IO_ERROR );
-
 #if defined(DEBUG)
     void Show( int nestLevel, std::ostream& os ) const;     // overload
 #endif
diff --git a/pcbnew/class_edge_mod.cpp b/pcbnew/class_edge_mod.cpp
index bc8b84f053..b1ef13eef4 100644
--- a/pcbnew/class_edge_mod.cpp
+++ b/pcbnew/class_edge_mod.cpp
@@ -279,16 +279,6 @@ EDA_ITEM* EDGE_MODULE::Clone() const
 }
 
 
-void EDGE_MODULE::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-    throw( IO_ERROR )
-{
-    aFormatter->Print( aNestLevel, "(edge (start (xy %s)) (end (xy %s))\n",
-                       FMT_IU( m_Start0 ).c_str(), FMT_IU( m_End0 ).c_str() );
-    DRAWSEGMENT::Format( aFormatter, aNestLevel+1, aControlBits );
-    aFormatter->Print( aNestLevel, ")\n" );
-}
-
-
 #if defined(DEBUG)
 
 void EDGE_MODULE::Show( int nestLevel, std::ostream& os ) const
diff --git a/pcbnew/class_edge_mod.h b/pcbnew/class_edge_mod.h
index f626fa35d0..8b5b557d4b 100644
--- a/pcbnew/class_edge_mod.h
+++ b/pcbnew/class_edge_mod.h
@@ -87,9 +87,6 @@ public:
 
     EDA_ITEM* Clone() const;
 
-    void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-        throw( IO_ERROR );
-
 #if defined(DEBUG)
     void Show( int nestLevel, std::ostream& os ) const;     // overload
 #endif
diff --git a/pcbnew/class_mire.cpp b/pcbnew/class_mire.cpp
index e545b1f752..18bfc99849 100644
--- a/pcbnew/class_mire.cpp
+++ b/pcbnew/class_mire.cpp
@@ -223,23 +223,3 @@ EDA_ITEM* PCB_TARGET::Clone() const
 {
     return new PCB_TARGET( *this );
 }
-
-
-void PCB_TARGET::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-    throw( IO_ERROR )
-{
-    aFormatter->Print( aNestLevel, "(target %c (pos (xy %s)) (size %s)",
-                       ( m_Shape ) ? 'x' : '+',
-                       FMT_IU( m_Pos ).c_str(),
-                       FMT_IU( m_Size ).c_str() );
-
-    if( m_Width != 0 )
-        aFormatter->Print( aNestLevel, " (width %s)", FMT_IU( m_Width ).c_str() );
-
-    aFormatter->Print( aNestLevel, " (layer %d)", GetLayer() );
-
-    if( GetTimeStamp() )
-        aFormatter->Print( aNestLevel, " (tstamp %lX)", GetTimeStamp() );
-
-    aFormatter->Print( aNestLevel, ")\n" );
-}
diff --git a/pcbnew/class_mire.h b/pcbnew/class_mire.h
index 8d73f92163..a874ed7e2d 100644
--- a/pcbnew/class_mire.h
+++ b/pcbnew/class_mire.h
@@ -103,9 +103,6 @@ public:
 
     EDA_ITEM* Clone() const;
 
-    void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-        throw( IO_ERROR );
-
 #if defined(DEBUG)
     void Show( int nestLevel, std::ostream& os ) const { ShowDummy( os ); } // override
 #endif
diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp
index bc5c615786..e8020e4682 100644
--- a/pcbnew/class_module.cpp
+++ b/pcbnew/class_module.cpp
@@ -664,125 +664,6 @@ EDA_ITEM* MODULE::Clone() const
 }
 
 
-void MODULE::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-    throw( IO_ERROR )
-{
-    aFormatter->Print( aNestLevel, "(module %s" , aFormatter->Quotew( m_LibRef ).c_str() );
-
-    if( IsLocked() )
-        aFormatter->Print( aNestLevel, " locked" );
-
-    if( IsPlaced() )
-        aFormatter->Print( aNestLevel, " placed" );
-
-    aFormatter->Print( 0, " (tedit %lX) (tstamp %lX)\n",
-                       GetLastEditTime(), GetTimeStamp() );
-
-    aFormatter->Print( aNestLevel+1, "(at %s", FMT_IU( m_Pos ).c_str() );
-
-    if( m_Orient != 0.0 )
-        aFormatter->Print( 0, " %s", FMT_ANGLE( m_Orient ).c_str() );
-
-    aFormatter->Print( 0, ")\n" );
-
-    if( !m_Doc.IsEmpty() )
-        aFormatter->Print( aNestLevel+1, "(descr %s)\n", aFormatter->Quotew( m_Doc ).c_str() );
-
-    if( !m_KeyWord.IsEmpty() )
-        aFormatter->Print( aNestLevel+1, "(tags %s)\n", aFormatter->Quotew( m_KeyWord ).c_str() );
-
-    if( !m_Path.IsEmpty() )
-        aFormatter->Print( aNestLevel+1, "(path %s)\n", aFormatter->Quotew( m_Path ).c_str() );
-
-    if( m_CntRot90 != 0 )
-        aFormatter->Print( aNestLevel+1, "(autoplace_cost90 %d)\n", m_CntRot90 );
-
-    if( m_CntRot180 != 0 )
-        aFormatter->Print( aNestLevel+1, "(autoplace_cost180 %d)\n", m_CntRot180 );
-
-    if( m_LocalSolderMaskMargin != 0 )
-        aFormatter->Print( aNestLevel+1, "(solder_mask_margin %s)\n",
-                           FMT_IU( m_LocalSolderMaskMargin ).c_str() );
-
-    if( m_LocalSolderPasteMargin != 0 )
-        aFormatter->Print( aNestLevel+1, "(solder_paste_margin %s)\n",
-                           FMT_IU( m_LocalSolderPasteMargin ).c_str() );
-
-    if( m_LocalSolderPasteMarginRatio != 0 )
-        aFormatter->Print( aNestLevel+1, "(solder_paste_ratio %g)\n",
-                           m_LocalSolderPasteMarginRatio );
-
-    if( m_LocalClearance != 0 )
-        aFormatter->Print( aNestLevel+1, "(clearance %s)\n",
-                           FMT_IU( m_LocalClearance ).c_str() );
-
-    if( m_ZoneConnection != UNDEFINED_CONNECTION )
-        aFormatter->Print( aNestLevel+1, "(zone_connect %d)\n", m_ZoneConnection );
-
-    if( m_ThermalWidth != 0 )
-        aFormatter->Print( aNestLevel+1, "(thermal_width %s)\n",
-                           FMT_IU( m_ThermalWidth ).c_str() );
-
-    if( m_ThermalGap != 0 )
-        aFormatter->Print( aNestLevel+1, "(thermal_gap %s)\n",
-                           FMT_IU( m_ThermalGap ).c_str() );
-
-    // Attributes
-    if( m_Attributs != MOD_DEFAULT )
-    {
-        aFormatter->Print( aNestLevel+1, "(attr " );
-
-        if( m_Attributs & MOD_CMS )
-            aFormatter->Print( 0, " smd" );
-
-        if( m_Attributs & MOD_VIRTUAL )
-            aFormatter->Print( 0, " virtual" );
-
-        aFormatter->Print( 0, ")\n" );
-    }
-
-    m_Reference->Format( aFormatter, aNestLevel+1, aControlBits );
-    m_Value->Format( aFormatter, aNestLevel+1, aControlBits );
-
-    // Save drawing elements.
-    for( BOARD_ITEM* gr = m_Drawings;  gr;  gr = gr->Next() )
-        gr->Format( aFormatter, aNestLevel+1, aControlBits );
-
-    // Save pads.
-    for( D_PAD* pad = m_Pads;  pad;  pad = pad->Next() )
-        pad->Format( aFormatter, aNestLevel+1, aControlBits );
-
-    // Save 3D info.
-    for( S3D_MASTER* t3D = m_3D_Drawings;  t3D;  t3D = t3D->Next() )
-    {
-        if( !t3D->m_Shape3DName.IsEmpty() )
-        {
-            aFormatter->Print( aNestLevel+1, "(3d_shape %s\n",
-                               aFormatter->Quotew( t3D->m_Shape3DName ).c_str() );
-
-            aFormatter->Print( aNestLevel+2, "(at (xyz %.16g %.16g %.16g))\n",
-                               t3D->m_MatPosition.x,
-                               t3D->m_MatPosition.y,
-                               t3D->m_MatPosition.z );
-
-            aFormatter->Print( aNestLevel+2, "(scale (xyz %.16g %.16g %.16g))\n",
-                               t3D->m_MatScale.x,
-                               t3D->m_MatScale.y,
-                               t3D->m_MatScale.z );
-
-            aFormatter->Print( aNestLevel+2, "(rotate (xyz %.16g %.16g %.16g))\n",
-                               t3D->m_MatRotation.x,
-                               t3D->m_MatRotation.y,
-                               t3D->m_MatRotation.z );
-
-            aFormatter->Print( aNestLevel+1, ")\n" );
-        }
-    }
-
-    aFormatter->Print( aNestLevel, ")\n" );
-}
-
-
 #if defined(DEBUG)
 
 void MODULE::Show( int nestLevel, std::ostream& os ) const
diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h
index 135b0f8f1b..130d0d2c21 100644
--- a/pcbnew/class_module.h
+++ b/pcbnew/class_module.h
@@ -334,9 +334,6 @@ public:
 
     EDA_ITEM* Clone() const;
 
-    void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-        throw( IO_ERROR );
-
 #if defined(DEBUG)
     void Show( int nestLevel, std::ostream& os ) const;     // overload
 #endif
diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp
index 1c91dd4054..0ee5d847b3 100644
--- a/pcbnew/class_pad.cpp
+++ b/pcbnew/class_pad.cpp
@@ -830,101 +830,6 @@ EDA_ITEM* D_PAD::Clone() const
 }
 
 
-void D_PAD::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-    throw( IO_ERROR )
-{
-    std::string shape;
-
-    switch( m_PadShape )
-    {
-    case PAD_CIRCLE:    shape = "circle";     break;
-    case PAD_RECT:      shape = "rectangle";  break;
-    case PAD_OVAL:      shape = "oval";       break;
-    case PAD_TRAPEZOID: shape = "trapezoid";  break;
-
-    default:
-        THROW_IO_ERROR( wxString::Format( _( "unknown pad type: %d"), m_PadShape ) );
-    }
-
-    std::string type;
-
-    switch( m_Attribute )
-    {
-    case PAD_STANDARD:          type = "thru_hole";      break;
-    case PAD_SMD:               type = "smd";            break;
-    case PAD_CONN:              type = "connect";        break;
-    case PAD_HOLE_NOT_PLATED:   type = "np_thru_hole";   break;
-
-    default:
-        THROW_IO_ERROR( wxString::Format( _( "unknown pad attribute: %d" ), m_Attribute ) );
-    }
-
-    aFormatter->Print( aNestLevel, "(pad %s %s %s (size %s)\n",
-                       aFormatter->Quotew( GetPadName() ).c_str(), type.c_str(), shape.c_str(),
-                       FMT_IU( m_Size ).c_str() );
-    aFormatter->Print( aNestLevel+1, "(at %s", FMT_IU( m_Pos0 ).c_str() );
-
-    if( m_Orient != 0.0 )
-        aFormatter->Print( 0, " %s", FMT_ANGLE( m_Orient ).c_str() );
-
-    aFormatter->Print( 0, ")\n" );
-
-    if( (m_Drill.GetWidth() > 0) || (m_Drill.GetHeight() > 0) )
-    {
-        std::string drill = (m_Drill.GetHeight() > 0) ? FMT_IU( m_Drill ).c_str() :
-                            FMT_IU( m_Drill.GetWidth() ).c_str();
-        aFormatter->Print( aNestLevel+1, "(drill %s", drill.c_str() );
-
-        if( (m_Offset.x > 0) || (m_Offset.y > 0) )
-        {
-            std::string drillOffset = ( m_Offset.x > 0 ) ?
-                                      FMT_IU( m_Offset ).c_str() :
-                                      FMT_IU( m_Offset.x ).c_str();
-            aFormatter->Print( 0, " (offset %s)", drillOffset.c_str() );
-        }
-
-        aFormatter->Print( 0, ")\n" );
-    }
-
-    aFormatter->Print( aNestLevel+1, "(layers %08X)\n", GetLayerMask() );
-
-    aFormatter->Print( aNestLevel+1, "(net %d %s)\n",
-                       GetNet(), aFormatter->Quotew( m_Netname ).c_str() );
-
-    if( m_LengthDie != 0 )
-        aFormatter->Print( aNestLevel+1, "(die_length %s)\n", FMT_IU( m_LengthDie ).c_str() );
-
-    if( m_LocalSolderMaskMargin != 0 )
-        aFormatter->Print( aNestLevel+1, "(solder_mask_margin %s)\n",
-                           FMT_IU( m_LocalSolderMaskMargin ).c_str() );
-
-    if( m_LocalSolderPasteMargin != 0 )
-        aFormatter->Print( aNestLevel+1, "(solder_paste_margin %s)\n",
-                           FMT_IU( m_LocalSolderPasteMargin ).c_str() );
-
-    if( m_LocalSolderPasteMarginRatio != 0 )
-        aFormatter->Print( aNestLevel+1, "(solder_paste_margin_ratio %g)\n",
-                           m_LocalSolderPasteMarginRatio );
-
-    if( m_LocalClearance != 0 )
-        aFormatter->Print( aNestLevel+1, "(clearance %s)\n",
-                           FMT_IU( m_LocalClearance ).c_str() );
-
-    if( GetZoneConnection() != UNDEFINED_CONNECTION )
-        aFormatter->Print( aNestLevel+1, "(zone_connect %d)\n", GetZoneConnection() );
-
-    if( GetThermalWidth() != 0 )
-        aFormatter->Print( aNestLevel+1, "(thermal_width %s)\n",
-                           FMT_IU( GetThermalWidth() ).c_str() );
-
-    if( GetThermalGap() != 0 )
-        aFormatter->Print( aNestLevel+1, "(thermal_gap %s)\n",
-                           FMT_IU( GetThermalGap() ).c_str() );
-
-    aFormatter->Print( aNestLevel, ")\n" );
-}
-
-
 #if defined(DEBUG)
 
 void D_PAD::Show( int nestLevel, std::ostream& os ) const
diff --git a/pcbnew/class_pad.h b/pcbnew/class_pad.h
index 92b5c76e14..46413578c1 100644
--- a/pcbnew/class_pad.h
+++ b/pcbnew/class_pad.h
@@ -392,9 +392,6 @@ public:
 
     EDA_ITEM* Clone() const;
 
-    void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-        throw( IO_ERROR );
-
 #if defined(DEBUG)
     void Show( int nestLevel, std::ostream& os ) const;     // overload
 #endif
diff --git a/pcbnew/class_pcb_text.cpp b/pcbnew/class_pcb_text.cpp
index bc9d559fc3..ec265d1ef3 100644
--- a/pcbnew/class_pcb_text.cpp
+++ b/pcbnew/class_pcb_text.cpp
@@ -191,22 +191,6 @@ EDA_ITEM* TEXTE_PCB::Clone() const
 }
 
 
-void TEXTE_PCB::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-    throw( IO_ERROR )
-{
-    aFormatter->Print( aNestLevel, "(pcb_text (layer %d)", GetLayer() );
-
-    if( GetTimeStamp() )
-        aFormatter->Print( 0, " (tstamp %lX)", GetTimeStamp() );
-
-    aFormatter->Print( 0, "\n" );
-
-    EDA_TEXT::Format( aFormatter, aNestLevel+1, aControlBits );
-
-    aFormatter->Print( aNestLevel, ")\n" );
-}
-
-
 #if defined(DEBUG)
 
 void TEXTE_PCB::Show( int nestLevel, std::ostream& os ) const
diff --git a/pcbnew/class_pcb_text.h b/pcbnew/class_pcb_text.h
index 7df987a65e..6b6191c1ef 100644
--- a/pcbnew/class_pcb_text.h
+++ b/pcbnew/class_pcb_text.h
@@ -115,9 +115,6 @@ public:
 
     EDA_ITEM* Clone() const;
 
-    void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-        throw( IO_ERROR );
-
 #if defined(DEBUG)
     void Show( int nestLevel, std::ostream& os ) const;
 #endif
diff --git a/pcbnew/class_text_mod.cpp b/pcbnew/class_text_mod.cpp
index 9541f62cd4..279489a06f 100644
--- a/pcbnew/class_text_mod.cpp
+++ b/pcbnew/class_text_mod.cpp
@@ -480,26 +480,6 @@ EDA_ITEM* TEXTE_MODULE::Clone() const
 }
 
 
-void TEXTE_MODULE::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-    throw( IO_ERROR )
-{
-    MODULE* parent = (MODULE*) GetParent();
-    double  orient = GetOrientation();
-
-    // Due to the Pcbnew history, m_Orient is saved in screen value
-    // but it is handled as relative to its parent footprint
-    if( parent )
-        orient += parent->GetOrientation();
-
-    aFormatter->Print( aNestLevel, "(module_text %d (at %s %0.1f)%s\n", m_Type,
-                       FMT_IU( m_Pos0 ).c_str(), orient, (m_NoShow) ? "hide" : "" );
-
-    EDA_TEXT::Format( aFormatter, aNestLevel+1, aControlBits );
-
-    aFormatter->Print( aNestLevel, ")\n" );
-}
-
-
 #if defined(DEBUG)
 
 void TEXTE_MODULE::Show( int nestLevel, std::ostream& os ) const
diff --git a/pcbnew/class_text_mod.h b/pcbnew/class_text_mod.h
index e2f4136cbd..68c6b0c461 100644
--- a/pcbnew/class_text_mod.h
+++ b/pcbnew/class_text_mod.h
@@ -166,9 +166,6 @@ public:
 
     EDA_ITEM* Clone() const;
 
-    void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-        throw( IO_ERROR );
-
 #if defined(DEBUG)
     void Show( int nestLevel, std::ostream& os ) const;     // overload
 #endif
diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp
index dc79f6181a..2ae5d9add1 100644
--- a/pcbnew/class_track.cpp
+++ b/pcbnew/class_track.cpp
@@ -1559,47 +1559,6 @@ wxString TRACK::GetSelectMenuText() const
 }
 
 
-void TRACK::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-    throw( IO_ERROR )
-{
-    if( Type() == PCB_VIA_T )
-    {
-        std::string type;
-
-        switch( m_Shape )
-        {
-        case VIA_THROUGH:       type = "thru";     break;
-        case VIA_BLIND_BURIED:  type = "blind";    break;
-        case VIA_MICROVIA:      type = "micro";    break;
-        default:
-            THROW_IO_ERROR( wxString::Format( _( "unknown via type %d"  ), m_Shape ) );
-        }
-
-        aFormatter->Print( aNestLevel, "(via %s (at %s) (size %s)", type.c_str(),
-                           FMT_IU( m_Start ).c_str(), FMT_IU( m_Width ).c_str() );
-
-        if( m_Drill != UNDEFINED_DRILL_DIAMETER )
-            aFormatter->Print( 0, " (drill %s)", FMT_IU( m_Drill ).c_str() );
-    }
-    else
-    {
-        aFormatter->Print( aNestLevel, "(segment (start %s) (end %s) (width %s)",
-                           FMT_IU( m_Start ).c_str(), FMT_IU( m_End ).c_str(),
-                           FMT_IU( m_Width ).c_str() );
-    }
-
-    aFormatter->Print( 0, " (layer %d) (net %d)", GetLayer(), GetNet() );
-
-    if( GetTimeStamp() != 0 )
-        aFormatter->Print( 0, " (tstamp %lX)", GetTimeStamp() );
-
-    if( GetStatus() != 0 )
-        aFormatter->Print( 0, " (status %X)", GetStatus() );
-
-    aFormatter->Print( 0, ")\n" );
-}
-
-
 #if defined(DEBUG)
 
 void TRACK::Show( int nestLevel, std::ostream& os ) const
diff --git a/pcbnew/class_track.h b/pcbnew/class_track.h
index 328c1e0eb1..14a22a651e 100644
--- a/pcbnew/class_track.h
+++ b/pcbnew/class_track.h
@@ -333,9 +333,6 @@ public:
 
     virtual EDA_ITEM* Clone() const;
 
-    void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-        throw( IO_ERROR );
-
 #if defined (DEBUG)
 
     void Show( int nestLevel, std::ostream& os ) const;     // overload
diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp
index 1732eef0e2..d6e2b1c1e3 100644
--- a/pcbnew/class_zone.cpp
+++ b/pcbnew/class_zone.cpp
@@ -955,145 +955,3 @@ wxString ZONE_CONTAINER::GetSelectMenuText() const
 
     return text;
 }
-
-
-void ZONE_CONTAINER::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-    throw( IO_ERROR )
-{
-    aFormatter->Print( aNestLevel, "(zone (net %d %s) (layer %d) (tstamp %lX)\n",
-                       GetNet(), aFormatter->Quotew( m_Netname ).c_str(),
-                       GetLayer(), GetTimeStamp() );
-
-
-    // Save the outline aux info
-    std::string hatch;
-
-    switch( GetHatchStyle() )
-    {
-    default:
-    case CPolyLine::NO_HATCH:       hatch = "none";    break;
-    case CPolyLine::DIAGONAL_EDGE:  hatch = "edge";    break;
-    case CPolyLine::DIAGONAL_FULL:  hatch = "full";    break;
-    }
-
-    aFormatter->Print( aNestLevel+1, "(hatch %s)\n", hatch.c_str() );
-
-    if( m_priority > 0 )
-        aFormatter->Print( aNestLevel+1, "(priority %d)\n", m_priority );
-
-    // Save pad option and clearance
-    std::string padoption;
-
-    switch( GetPadConnection() )
-    {
-    default:
-    case PAD_IN_ZONE:       padoption = "yes";          break;
-    case THERMAL_PAD:       padoption = "use_thermal";  break;
-    case PAD_NOT_IN_ZONE:   padoption = "no";           break;
-    }
-
-    aFormatter->Print( aNestLevel+1, "(connect_pads %s (clearance %s))\n",
-                       padoption.c_str(), FMT_IU( m_ZoneClearance ).c_str() );
-
-    aFormatter->Print( aNestLevel+1, "(min_thickness %s)\n",
-                       FMT_IU( m_ZoneMinThickness ).c_str() );
-
-    aFormatter->Print( aNestLevel+1,
-                       "(fill %s (mode %s) (arc_segments %d) (thermal_gap %s) (thermal_bridge_width %s)\n",
-                       (m_IsFilled) ? "yes" : "no",
-                       (m_FillMode) ? "segment" : "polygon",
-                       m_ArcToSegmentsCount,
-                       FMT_IU( m_ThermalReliefGap ).c_str(),
-                       FMT_IU( m_ThermalReliefCopperBridge ).c_str() );
-
-    std::string smoothing;
-
-    switch( cornerSmoothingType )
-    {
-    case ZONE_SETTINGS::SMOOTHING_NONE:      smoothing = "none";      break;
-    case ZONE_SETTINGS::SMOOTHING_CHAMFER:   smoothing = "chamfer";   break;
-    case ZONE_SETTINGS::SMOOTHING_FILLET:    smoothing = "fillet";    break;
-    default:
-        THROW_IO_ERROR( wxString::Format( _( "unknown zone corner smoothing type %d"  ),
-                                          cornerSmoothingType ) );
-    }
-
-    aFormatter->Print( aNestLevel+1, "(smoothing %s (radius %s))\n",
-                       smoothing.c_str(), FMT_IU( cornerRadius ).c_str() );
-
-    const std::vector< CPolyPt >& cv = m_Poly->corner;
-
-    if( cv.size() )
-    {
-        aFormatter->Print( aNestLevel+1, "(polygon\n");
-        aFormatter->Print( aNestLevel+2, "(pts\n" );
-
-        for( std::vector< CPolyPt >::const_iterator it = cv.begin();  it != cv.end();  ++it )
-        {
-            aFormatter->Print( aNestLevel+3, "(xy %s %s)\n",
-                               FMT_IU( it->x ).c_str(), FMT_IU( it->y ).c_str() );
-
-            if( it->end_contour )
-            {
-                aFormatter->Print( aNestLevel+2, ")\n" );
-
-                if( it+1 != cv.end() )
-                {
-                    aFormatter->Print( aNestLevel+1, ")\n" );
-                    aFormatter->Print( aNestLevel+1, "(polygon\n" );
-                    aFormatter->Print( aNestLevel+2, "(pts\n" );
-                }
-            }
-        }
-
-        aFormatter->Print( aNestLevel+1, ")\n" );
-    }
-
-    // Save the PolysList
-    const std::vector< CPolyPt >& fv = m_FilledPolysList;
-
-    if( fv.size() )
-    {
-        aFormatter->Print( aNestLevel+1, "(filled_polygon\n" );
-        aFormatter->Print( aNestLevel+2, "(pts\n" );
-
-        for( std::vector< CPolyPt >::const_iterator it = fv.begin();  it != fv.end();  ++it )
-        {
-            aFormatter->Print( aNestLevel+3, "(xy %s %s)\n",
-                               FMT_IU( it->x ).c_str(), FMT_IU( it->y ).c_str() );
-
-            if( it->end_contour )
-            {
-                aFormatter->Print( aNestLevel+2, ")\n" );
-
-                if( it+1 != fv.end() )
-                {
-                    aFormatter->Print( aNestLevel+1, ")\n" );
-                    aFormatter->Print( aNestLevel+1, "(filled_polygon\n" );
-                    aFormatter->Print( aNestLevel+2, "(pts\n" );
-                }
-            }
-        }
-
-        aFormatter->Print( aNestLevel+1, ")\n" );
-    }
-
-    // Save the filling segments list
-    const std::vector< SEGMENT >& segs = m_FillSegmList;
-
-    if( segs.size() )
-    {
-        aFormatter->Print( aNestLevel+1, "(fill_segments\n" );
-
-        for( std::vector< SEGMENT >::const_iterator it = segs.begin();  it != segs.end();  ++it )
-        {
-            aFormatter->Print( aNestLevel+2, "(pts (xy %s) (xy %s))\n",
-                               FMT_IU( it->m_Start ).c_str(),
-                               FMT_IU( it->m_End ).c_str() );
-        }
-
-        aFormatter->Print( aNestLevel+1, ")\n" );
-    }
-
-    aFormatter->Print( aNestLevel, ")\n" );
-}
diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h
index a7bea558d0..645e3bad85 100644
--- a/pcbnew/class_zone.h
+++ b/pcbnew/class_zone.h
@@ -544,9 +544,6 @@ public:
 
     virtual EDA_ITEM* Clone() const;
 
-    void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
-        throw( IO_ERROR );
-
 #if defined(DEBUG)
     void Show( int nestLevel, std::ostream& os ) const { ShowDummy( os ); } // override
 #endif
diff --git a/pcbnew/io_mgr.cpp b/pcbnew/io_mgr.cpp
index dd00e4027a..f8ca28804f 100644
--- a/pcbnew/io_mgr.cpp
+++ b/pcbnew/io_mgr.cpp
@@ -58,7 +58,7 @@ PLUGIN* IO_MGR::PluginFind( PCB_FILE_T aFileType )
         return new LEGACY_PLUGIN();
 
     case KICAD:
-        return new KICAD_PLUGIN();
+        return new PCB_IO();
 
 /*
     case EAGLE:
diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp
index acb2c6ae14..cbae672f75 100644
--- a/pcbnew/kicad_plugin.cpp
+++ b/pcbnew/kicad_plugin.cpp
@@ -28,13 +28,26 @@
 #include <common.h>
 #include <build_version.h>      // LEGACY_BOARD_FILE_VERSION
 
+#include <3d_struct.h>
+
 #include <class_board.h>
+#include <class_module.h>
+#include <class_pcb_text.h>
+#include <class_dimension.h>
+#include <class_track.h>
+#include <class_zone.h>
+#include <class_drawsegment.h>
+#include <class_mire.h>
+#include <class_edge_mod.h>
+#include <zones.h>
 #include <kicad_plugin.h>
 
 #include <wx/wfstream.h>
 
+#define FMTIU        BOARD_ITEM::FormatInternalUnits
 
-void KICAD_PLUGIN::Save( const wxString& aFileName, BOARD* aBoard, PROPERTIES* aProperties )
+
+void PCB_IO::Save( const wxString& aFileName, BOARD* aBoard, PROPERTIES* aProperties )
 {
     LOCALE_IO toggle;     // toggles on, then off, the C locale.
 
@@ -52,6 +65,955 @@ void KICAD_PLUGIN::Save( const wxString& aFileName, BOARD* aBoard, PROPERTIES* a
 
     formatter.Print( 0, "(kicad-board (version %d) (host pcbnew %s)\n", SEXPR_BOARD_FILE_VERSION,
                      formatter.Quotew( GetBuildVersion() ).c_str() );
-    aBoard->Format( (OUTPUTFORMATTER*) &formatter, 1, 0 );
+    Format( aBoard, (OUTPUTFORMATTER*) &formatter, 1, 0 );
     formatter.Print( 0, ")\n" );
 }
+
+
+void PCB_IO::Format( BOARD_ITEM* aItem, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                     int aControlBits ) const
+    throw( IO_ERROR )
+{
+    switch( aItem->Type() )
+    {
+    case PCB_T:
+        format( (BOARD*) aItem, aFormatter, aNestLevel, aControlBits );
+        break;
+
+    case PCB_DIMENSION_T:
+        format( ( DIMENSION*) aItem, aFormatter, aNestLevel, aControlBits );
+        break;
+
+    case PCB_LINE_T:
+        format( (DRAWSEGMENT*) aItem, aFormatter, aNestLevel, aControlBits );
+        break;
+
+    case PCB_MODULE_EDGE_T:
+        format( (EDGE_MODULE*) aItem, aFormatter, aNestLevel, aControlBits );
+        break;
+
+    case PCB_TARGET_T:
+        format( (PCB_TARGET*) aItem, aFormatter, aNestLevel, aControlBits );
+        break;
+
+    case PCB_MODULE_T:
+        format( (MODULE*) aItem, aFormatter, aNestLevel, aControlBits );
+        break;
+
+    case PCB_PAD_T:
+        format( (D_PAD*) aItem, aFormatter, aNestLevel, aControlBits );
+        break;
+
+    case PCB_TEXT_T:
+        format( (TEXTE_PCB*) aItem, aFormatter, aNestLevel, aControlBits );
+        break;
+
+    case PCB_MODULE_TEXT_T:
+        format( (TEXTE_MODULE*) aItem, aFormatter, aNestLevel, aControlBits );
+        break;
+
+    case PCB_TRACE_T:
+    case PCB_VIA_T:
+        format( (TRACK*) aItem, aFormatter, aNestLevel, aControlBits );
+        break;
+
+    case PCB_ZONE_AREA_T:
+        format( (ZONE_CONTAINER*) aItem, aFormatter, aNestLevel, aControlBits );
+        break;
+
+    default:
+        wxFAIL_MSG( wxT( "Cannot format item " ) + aItem->GetClass() );
+    }
+}
+
+
+void PCB_IO::format( BOARD* aBoard, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                     int aControlBits ) const
+    throw( IO_ERROR )
+{
+    aFormatter->Print( aNestLevel, ")\n" );
+    aFormatter->Print( 0, "\n" );
+
+    aFormatter->Print( aNestLevel, "(general\n" );
+    aFormatter->Print( aNestLevel+1, "(links %d)\n", aBoard->GetRatsnestsCount() );
+    aFormatter->Print( aNestLevel+1, "(no_connects %d)\n", aBoard->m_NbNoconnect );
+
+    // Write Bounding box info
+    aFormatter->Print( aNestLevel+1,  "(area %s %s %s %s)\n",
+                       FMTIU( aBoard->GetBoundingBox().GetX() ).c_str(),
+                       FMTIU( aBoard->GetBoundingBox().GetY() ).c_str(),
+                       FMTIU( aBoard->GetBoundingBox().GetRight() ).c_str(),
+                       FMTIU( aBoard->GetBoundingBox().GetBottom() ).c_str() );
+    aFormatter->Print( aNestLevel+1, "(thickness %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_BoardThickness ).c_str() );
+
+    aFormatter->Print( aNestLevel+1, "(drawings %d)\n", aBoard->m_Drawings.GetCount() );
+    aFormatter->Print( aNestLevel+1, "(tracks %d)\n", aBoard->GetNumSegmTrack() );
+    aFormatter->Print( aNestLevel+1, "(zones %d)\n", aBoard->GetNumSegmZone() );
+    aFormatter->Print( aNestLevel+1, "(modules %d)\n", aBoard->m_Modules.GetCount() );
+    aFormatter->Print( aNestLevel+1, "(nets %d)\n", aBoard->GetNetCount() );
+    aFormatter->Print( aNestLevel, ")\n\n" );
+
+    aBoard->GetPageSettings().Format( aFormatter, aNestLevel, aControlBits );
+    aBoard->GetTitleBlock().Format( aFormatter, aNestLevel, aControlBits );
+
+    // Layers.
+    aFormatter->Print( aNestLevel, "(layers %d %08X", aBoard->GetCopperLayerCount(),
+                       aBoard->GetEnabledLayers() );
+
+    if( aBoard->GetEnabledLayers() != aBoard->GetVisibleLayers() )
+        aFormatter->Print( 0, " %08X", aBoard->GetVisibleLayers() );
+
+    aFormatter->Print( 0, "\n" );
+
+    unsigned layerMask = ALL_CU_LAYERS & aBoard->GetEnabledLayers();
+
+    for( int layer = 0;  layerMask;  ++layer, layerMask >>= 1 )
+    {
+        if( layerMask & 1 )
+        {
+            aFormatter->Print( aNestLevel+1, "(layer%d %s %s)\n", layer,
+                               aFormatter->Quotew( aBoard->GetLayerName( layer ) ).c_str(),
+                               LAYER::ShowType( aBoard->GetLayerType( layer ) ) );
+        }
+    }
+
+    aFormatter->Print( aNestLevel, ")\n\n" );
+
+    // Setup
+    aFormatter->Print( aNestLevel, "(setup\n" );
+
+    // Save current default track width, for compatibility with older Pcbnew version;
+    aFormatter->Print( aNestLevel+1, "(last_trace_width %s)\n",
+                       FMTIU( aBoard->m_TrackWidthList[aBoard->m_TrackWidthSelector] ).c_str() );
+
+    // Save custom tracks width list (the first is not saved here: this is the netclass value
+    for( unsigned ii = 1; ii < aBoard->m_TrackWidthList.size(); ii++ )
+        aFormatter->Print( aNestLevel+1, "(user_trace_width%d %s)\n",
+                           ii+1, FMTIU( aBoard->m_TrackWidthList[ii] ).c_str() );
+
+    aFormatter->Print( aNestLevel+1, "(trace_clearance %s)\n",
+                       FMTIU( aBoard->m_NetClasses.GetDefault()->GetClearance() ).c_str() );
+
+    // ZONE_SETTINGS
+    aFormatter->Print( aNestLevel+1, "(zone_clearance %s)\n",
+                       FMTIU( aBoard->GetZoneSettings().m_ZoneClearance ).c_str() );
+    aFormatter->Print( aNestLevel+1, "(zone_45_only %d)\n",
+                       aBoard->GetZoneSettings().m_Zone_45_Only );
+
+    aFormatter->Print( aNestLevel+1, "(trace_min %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_TrackMinWidth ).c_str() );
+
+    aFormatter->Print( aNestLevel+1, "(segment_width %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_DrawSegmentWidth ).c_str() );
+    aFormatter->Print( aNestLevel+1, "(edge_width %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_EdgeSegmentWidth ).c_str() );
+
+    // Save current default via size, for compatibility with older Pcbnew version;
+    aFormatter->Print( aNestLevel+1, "(via_size %s)\n",
+                       FMTIU( aBoard->m_NetClasses.GetDefault()->GetViaDiameter() ).c_str() );
+    aFormatter->Print( aNestLevel+1, "(via_drill %s)\n",
+                       FMTIU( aBoard->m_NetClasses.GetDefault()->GetViaDrill() ).c_str() );
+    aFormatter->Print( aNestLevel+1, "(via_min_size %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_ViasMinSize ).c_str() );
+    aFormatter->Print( aNestLevel+1, "(via_min_drill %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_ViasMinDrill ).c_str() );
+
+    // Save custom vias diameters list (the first is not saved here: this is
+    // the netclass value
+    for( unsigned ii = 1; ii < aBoard->m_ViasDimensionsList.size(); ii++ )
+        aFormatter->Print( aNestLevel+1, "(user_via%d %s %s)\n", ii,
+                           FMTIU( aBoard->m_ViasDimensionsList[ii].m_Diameter ).c_str(),
+                           FMTIU( aBoard->m_ViasDimensionsList[ii].m_Drill ).c_str() );
+
+    // for old versions compatibility:
+    aFormatter->Print( aNestLevel+1, "(uvia_size %s)\n",
+                       FMTIU( aBoard->m_NetClasses.GetDefault()->GetuViaDiameter() ).c_str() );
+    aFormatter->Print( aNestLevel+1, "(uvia_drill %s)\n",
+                       FMTIU( aBoard->m_NetClasses.GetDefault()->GetuViaDrill() ).c_str() );
+    aFormatter->Print( aNestLevel+1, "(uvias_allow %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_MicroViasAllowed ).c_str() );
+    aFormatter->Print( aNestLevel+1, "(uvia_min_size %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_MicroViasMinSize ).c_str() );
+    aFormatter->Print( aNestLevel+1, "(uvia_min_drill %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_MicroViasMinDrill ).c_str() );
+
+    aFormatter->Print( aNestLevel+1, "(pcb_text_width %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_PcbTextWidth ).c_str() );
+    aFormatter->Print( aNestLevel+1, "(pcb_text_size %s %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_PcbTextSize.x ).c_str(),
+                       FMTIU( aBoard->GetDesignSettings().m_PcbTextSize.y ).c_str() );
+
+    aFormatter->Print( aNestLevel+1, "(mod_edge_width %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_ModuleSegmentWidth ).c_str() );
+    aFormatter->Print( aNestLevel+1, "(mod_text_size %s %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_ModuleTextSize.x ).c_str(),
+                       FMTIU( aBoard->GetDesignSettings().m_ModuleTextSize.y ).c_str() );
+    aFormatter->Print( aNestLevel+1, "(mod_text_width %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_ModuleTextWidth ).c_str() );
+
+    aFormatter->Print( aNestLevel+1, "(pad_size %s %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_Pad_Master.GetSize().x ).c_str(),
+                       FMTIU( aBoard->GetDesignSettings().m_Pad_Master.GetSize().x ).c_str() );
+    aFormatter->Print( aNestLevel+1, "(pad_drill %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_Pad_Master.GetDrillSize().x ).c_str() );
+
+    aFormatter->Print( aNestLevel+1, "(pad_to_mask_clearance %s)\n",
+                       FMTIU( aBoard->GetDesignSettings().m_SolderMaskMargin ).c_str() );
+
+    if( aBoard->GetDesignSettings().m_SolderPasteMargin != 0 )
+        aFormatter->Print( aNestLevel+1, "(pad_to_paste_clearance %s)\n",
+                           FMTIU( aBoard->GetDesignSettings().m_SolderPasteMargin ).c_str() );
+
+    if( aBoard->GetDesignSettings().m_SolderPasteMarginRatio != 0 )
+        aFormatter->Print( aNestLevel+1, "(pad_to_paste_clearance_ratio %g)\n",
+                           aBoard->GetDesignSettings().m_SolderPasteMarginRatio );
+
+    aFormatter->Print( aNestLevel+1, "(aux_axis_origin %s %s)\n",
+                       FMTIU( aBoard->GetOriginAxisPosition().x ).c_str(),
+                       FMTIU( aBoard->GetOriginAxisPosition().y ).c_str() );
+
+    aFormatter->Print( aNestLevel+1, "(visible_elements %X)\n",
+                       aBoard->GetDesignSettings().GetVisibleElements() );
+
+    aFormatter->Print( aNestLevel, ")\n\n" );
+
+
+    int netcount = aBoard->GetNetCount();
+
+    for( int i = 0;  i < netcount;  ++i )
+        aFormatter->Print( aNestLevel, "(net %d %s)\n",
+                           aBoard->FindNet( i )->GetNet(),
+                           aFormatter->Quotew( aBoard->FindNet( i )->GetNetname() ).c_str() );
+
+    aFormatter->Print( 0, "\n" );
+
+    // Save the default net class first.
+    aBoard->m_NetClasses.GetDefault()->Format( aFormatter, aNestLevel, aControlBits );
+
+    // Save the rest of the net classes alphabetically.
+    for( NETCLASSES::const_iterator it = aBoard->m_NetClasses.begin();
+         it != aBoard->m_NetClasses.end();
+         ++it )
+    {
+        NETCLASS* netclass = it->second;
+        netclass->Format( aFormatter, aNestLevel, aControlBits );
+    }
+
+    // Save the graphical items on the board (not owned by a module)
+    for( BOARD_ITEM* item = aBoard->m_Drawings;  item;  item = item->Next() )
+        Format( item, aFormatter, aNestLevel, aControlBits );
+
+    aFormatter->Print( 0, "\n" );
+
+    // Save the modules.
+    for( MODULE* module = aBoard->m_Modules;  module;  module = (MODULE*) module->Next() )
+    {
+        Format( module, aFormatter, aNestLevel, aControlBits );
+        aFormatter->Print( 0, "\n" );
+    }
+
+    // Do not save MARKER_PCBs, they can be regenerated easily.
+
+    // Save the tracks and vias.
+    for( TRACK* track = aBoard->m_Track;  track; track = track->Next() )
+        Format( track, aFormatter, aNestLevel, aControlBits );
+
+    /// @todo Add warning here that the old segment filed zones are no longer supported and
+    ///       will not be saved.
+
+    aFormatter->Print( 0, "\n" );
+
+    // Save the polygon (which are the newer technology) zones.
+    for( int i=0;  i < aBoard->GetAreaCount();  ++i )
+        Format( aBoard->GetArea( i ), aFormatter, aNestLevel, aControlBits );
+}
+
+
+void PCB_IO::format( DIMENSION* aDimension, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                     int aControlBits ) const
+    throw( IO_ERROR )
+{
+    aFormatter->Print( aNestLevel, "(dimension %s (width %s) (layer %s)",
+                       FMT_IU( aDimension->m_Value ).c_str(),
+                       FMT_IU( aDimension->m_Width ).c_str(),
+                        aFormatter->Quotew( aDimension->GetLayerName() ).c_str()  );
+
+     if( aDimension->GetTimeStamp() )
+         aFormatter->Print( 0, " (tstamp %lX)", aDimension->GetTimeStamp() );
+
+     aFormatter->Print( 0, "\n" );
+
+     Format( (TEXTE_PCB*) &aDimension->m_Text, aFormatter, aNestLevel+1, aControlBits );
+
+     aFormatter->Print( aNestLevel+1, "(feature1 pts((xy %s %s) (xy %s %s)))\n",
+                        FMT_IU( aDimension->m_featureLineDOx ).c_str(),
+                        FMT_IU( aDimension->m_featureLineDOy ).c_str(),
+                        FMT_IU( aDimension->m_featureLineDFx ).c_str(),
+                        FMT_IU( aDimension->m_featureLineDFy ).c_str() );
+
+     aFormatter->Print( aNestLevel+1, "(feature2 pts((xy %s %s) (xy %s %s)))\n",
+                        FMT_IU( aDimension->m_featureLineGOx ).c_str(),
+                        FMT_IU( aDimension->m_featureLineGOy ).c_str(),
+                        FMT_IU( aDimension->m_featureLineGFx ).c_str(),
+                        FMT_IU( aDimension->m_featureLineGFy ).c_str() );
+
+     aFormatter->Print( aNestLevel+1, "(crossbar pts((xy %s %s) (xy %s %s)))\n",
+                        FMT_IU( aDimension->m_crossBarOx ).c_str(),
+                        FMT_IU( aDimension->m_crossBarOy ).c_str(),
+                        FMT_IU( aDimension->m_crossBarFx ).c_str(),
+                        FMT_IU( aDimension->m_crossBarFy ).c_str() );
+
+     aFormatter->Print( aNestLevel+1, "(arrow1a pts((xy %s %s) (xy %s %s)))\n",
+                        FMT_IU( aDimension->m_arrowD1Ox ).c_str(),
+                        FMT_IU( aDimension->m_arrowD1Oy ).c_str(),
+                        FMT_IU( aDimension->m_arrowD1Fx ).c_str(),
+                        FMT_IU( aDimension->m_arrowD1Fy ).c_str() );
+
+     aFormatter->Print( aNestLevel+1, "(arrow1b pts((xy %s %s) (xy %s %s)))\n",
+                        FMT_IU( aDimension->m_arrowD2Ox ).c_str(),
+                        FMT_IU( aDimension->m_arrowD2Oy ).c_str(),
+                        FMT_IU( aDimension->m_arrowD2Fx ).c_str(),
+                        FMT_IU( aDimension->m_arrowD2Fy ).c_str() );
+
+     aFormatter->Print( aNestLevel+1, "(arrow2a pts((xy %s %s) (xy %s %s)))\n",
+                        FMT_IU( aDimension->m_arrowG1Ox ).c_str(),
+                        FMT_IU( aDimension->m_arrowG1Oy ).c_str(),
+                        FMT_IU( aDimension->m_arrowG1Fx ).c_str(),
+                        FMT_IU( aDimension->m_arrowG1Fy ).c_str() );
+
+     aFormatter->Print( aNestLevel+1, "(arrow2b pts((xy %s %s) (xy %s %s)))\n",
+                        FMT_IU( aDimension->m_arrowG2Ox ).c_str(),
+                        FMT_IU( aDimension->m_arrowG2Oy ).c_str(),
+                        FMT_IU( aDimension->m_arrowG2Fx ).c_str(),
+                        FMT_IU( aDimension->m_arrowG2Fy ).c_str() );
+
+     aFormatter->Print( aNestLevel, ")\n" );
+ }
+
+
+ void PCB_IO::format( DRAWSEGMENT* aSegment, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                      int aControlBits ) const
+     throw( IO_ERROR )
+ {
+     unsigned i;
+
+     switch( aSegment->GetShape() )
+     {
+     case S_SEGMENT:  // Line
+         aFormatter->Print( aNestLevel, "(gr_line (pts (xy %s) (xy %s))",
+                            FMT_IU( aSegment->GetStart() ).c_str(),
+                            FMT_IU( aSegment->GetEnd() ).c_str() );
+         break;
+
+     case S_CIRCLE:  // Circle
+         aFormatter->Print( aNestLevel, "(gr_circle (center (xy %s)) (end (xy %s))",
+                            FMT_IU( aSegment->GetStart() ).c_str(),
+                            FMT_IU( aSegment->GetEnd() ).c_str() );
+         break;
+
+     case S_ARC:     // Arc
+         aFormatter->Print( aNestLevel, "(gr_arc (start (xy %s)) (end (xy %s)) (angle %s)",
+                            FMT_IU( aSegment->GetStart() ).c_str(),
+                            FMT_IU( aSegment->GetEnd() ).c_str(),
+                            FMT_ANGLE( aSegment->GetAngle() ).c_str() );
+         break;
+
+     case S_POLYGON: // Polygon
+         aFormatter->Print( aNestLevel, "(gr_line (pts" );
+
+         for( i = 0;  i < aSegment->GetPolyPoints().size();  ++i )
+             aFormatter->Print( 0, " (xy %s)", FMT_IU( aSegment->GetPolyPoints()[i] ).c_str() );
+
+         aFormatter->Print( 0, ")" );
+         break;
+
+     case S_CURVE:   // Bezier curve
+         aFormatter->Print( aNestLevel, "(gr_curve pts(xy(%s) xy(%s) xy(%s) xy(%s))",
+                            FMT_IU( aSegment->GetStart() ).c_str(),
+                            FMT_IU( aSegment->GetBezControl1() ).c_str(),
+                            FMT_IU( aSegment->GetBezControl2() ).c_str(),
+                            FMT_IU( aSegment->GetEnd() ).c_str() );
+         break;
+
+     default:
+         wxFAIL_MSG( wxT( "Cannot format invalid DRAWSEGMENT type." ) );
+     };
+
+     aFormatter->Print( 0, " (layer %s)", aFormatter->Quotew( aSegment->GetLayerName() ).c_str() );
+
+    if( aSegment->GetWidth() != 0 )
+        aFormatter->Print( 0, " (width %s)", FMT_IU( aSegment->GetWidth() ).c_str() );
+
+    if( aSegment->GetTimeStamp() )
+        aFormatter->Print( 0, " (tstamp %lX)", aSegment->GetTimeStamp() );
+
+    if( aSegment->GetStatus() )
+        aFormatter->Print( 0, " (status %X)", aSegment->GetStatus() );
+
+    aFormatter->Print( 0, ")\n" );
+}
+
+
+void PCB_IO::format( EDGE_MODULE* aModuleDrawing, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                     int aControlBits ) const
+    throw( IO_ERROR )
+{
+    switch( aModuleDrawing->GetShape() )
+    {
+    case S_SEGMENT:  // Line
+        aFormatter->Print( aNestLevel, "(fp_line (pts (xy %s) (xy %s)",
+                           FMT_IU( aModuleDrawing->GetStart0() ).c_str(),
+                           FMT_IU( aModuleDrawing->GetEnd0() ).c_str() );
+        break;
+
+    case S_CIRCLE:  // Circle
+        aFormatter->Print( aNestLevel, "(fp_circle (center (xy %s)) (end (xy %s)",
+                           FMT_IU( aModuleDrawing->GetStart0() ).c_str(),
+                           FMT_IU( aModuleDrawing->GetEnd0() ).c_str() );
+        break;
+
+    case S_ARC:     // Arc
+        aFormatter->Print( aNestLevel, "(fp_arc (start (xy %s)) (end (xy %s)) (angle %s)",
+                           FMT_IU( aModuleDrawing->GetStart0() ).c_str(),
+                           FMT_IU( aModuleDrawing->GetEnd0() ).c_str(),
+                           FMT_ANGLE( aModuleDrawing->GetAngle() ).c_str() );
+        break;
+
+    case S_POLYGON: // Polygon
+        aFormatter->Print( aNestLevel, "(fp_poly (pts" );
+
+        for( unsigned i = 0;  i < aModuleDrawing->GetPolyPoints().size();  ++i )
+            aFormatter->Print( 0, " (xy %s)",
+                               FMT_IU( aModuleDrawing->GetPolyPoints()[i] ).c_str() );
+
+        break;
+
+    case S_CURVE:   // Bezier curve
+        aFormatter->Print( aNestLevel, "(fp_curve pts(xy(%s) xy(%s) xy(%s) xy(%s))",
+                           FMT_IU( aModuleDrawing->GetStart0() ).c_str(),
+                           FMT_IU( aModuleDrawing->GetBezControl1() ).c_str(),
+                           FMT_IU( aModuleDrawing->GetBezControl2() ).c_str(),
+                           FMT_IU( aModuleDrawing->GetEnd0() ).c_str() );
+        break;
+
+    default:
+        wxFAIL_MSG( wxT( "Cannot format invalid DRAWSEGMENT type." ) );
+    };
+
+    aFormatter->Print( 0, " (layer %s)",
+                       aFormatter->Quotew( aModuleDrawing->GetLayerName() ).c_str() );
+
+    if( aModuleDrawing->GetWidth() != 0 )
+        aFormatter->Print( 0, " (width %s)", FMT_IU( aModuleDrawing->GetWidth() ).c_str() );
+
+    if( aModuleDrawing->GetTimeStamp() )
+        aFormatter->Print( 0, " (tstamp %lX)", aModuleDrawing->GetTimeStamp() );
+
+    if( aModuleDrawing->GetStatus() )
+        aFormatter->Print( 0, " (status %X)", aModuleDrawing->GetStatus() );
+
+    aFormatter->Print( 0, ")\n" );
+}
+
+
+void PCB_IO::format( PCB_TARGET* aTarget, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                     int aControlBits ) const
+    throw( IO_ERROR )
+{
+    aFormatter->Print( aNestLevel, "(target %c (pos (xy %s)) (size %s)",
+                       ( aTarget->GetShape() ) ? 'x' : '+',
+                       FMT_IU( aTarget->GetPosition() ).c_str(),
+                       FMT_IU( aTarget->GetSize() ).c_str() );
+
+    if( aTarget->GetWidth() != 0 )
+        aFormatter->Print( aNestLevel, " (width %s)", FMT_IU( aTarget->GetWidth() ).c_str() );
+
+    aFormatter->Print( aNestLevel, " (layer %d)", aTarget->GetLayer() );
+
+    if( aTarget->GetTimeStamp() )
+        aFormatter->Print( aNestLevel, " (tstamp %lX)", aTarget->GetTimeStamp() );
+
+    aFormatter->Print( aNestLevel, ")\n" );
+}
+
+
+void PCB_IO::format( MODULE* aModule, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                     int aControlBits ) const
+    throw( IO_ERROR )
+{
+    aFormatter->Print( aNestLevel, "(module %s", aFormatter->Quotew( aModule->m_LibRef ).c_str() );
+
+    if( aModule->IsLocked() )
+        aFormatter->Print( aNestLevel, " locked" );
+
+    if( aModule->IsPlaced() )
+        aFormatter->Print( aNestLevel, " placed" );
+
+    aFormatter->Print( 0, " (tedit %lX) (tstamp %lX)\n",
+                       aModule->GetLastEditTime(), aModule->GetTimeStamp() );
+
+    aFormatter->Print( aNestLevel+1, "(at %s", FMT_IU( aModule->m_Pos ).c_str() );
+
+    if( aModule->m_Orient != 0.0 )
+        aFormatter->Print( 0, " %s", FMT_ANGLE( aModule->m_Orient ).c_str() );
+
+    aFormatter->Print( 0, ")\n" );
+
+    if( !aModule->m_Doc.IsEmpty() )
+        aFormatter->Print( aNestLevel+1, "(descr %s)\n",
+                           aFormatter->Quotew( aModule->m_Doc ).c_str() );
+
+    if( !aModule->m_KeyWord.IsEmpty() )
+        aFormatter->Print( aNestLevel+1, "(tags %s)\n",
+                           aFormatter->Quotew( aModule->m_KeyWord ).c_str() );
+
+    if( !aModule->m_Path.IsEmpty() )
+        aFormatter->Print( aNestLevel+1, "(path %s)\n",
+                           aFormatter->Quotew( aModule->m_Path ).c_str() );
+
+    if( aModule->m_CntRot90 != 0 )
+        aFormatter->Print( aNestLevel+1, "(autoplace_cost90 %d)\n", aModule->m_CntRot90 );
+
+    if( aModule->m_CntRot180 != 0 )
+        aFormatter->Print( aNestLevel+1, "(autoplace_cost180 %d)\n", aModule->m_CntRot180 );
+
+    if( aModule->GetLocalSolderMaskMargin() != 0 )
+        aFormatter->Print( aNestLevel+1, "(solder_mask_margin %s)\n",
+                           FMT_IU( aModule->GetLocalSolderMaskMargin() ).c_str() );
+
+    if( aModule->GetLocalSolderPasteMargin() != 0 )
+        aFormatter->Print( aNestLevel+1, "(solder_paste_margin %s)\n",
+                           FMT_IU( aModule->GetLocalSolderPasteMargin() ).c_str() );
+
+    if( aModule->GetLocalSolderPasteMarginRatio() != 0 )
+        aFormatter->Print( aNestLevel+1, "(solder_paste_ratio %g)\n",
+                           aModule->GetLocalSolderPasteMarginRatio() );
+
+    if( aModule->GetLocalClearance() != 0 )
+        aFormatter->Print( aNestLevel+1, "(clearance %s)\n",
+                           FMT_IU( aModule->GetLocalClearance() ).c_str() );
+
+    if( aModule->m_ZoneConnection != UNDEFINED_CONNECTION )
+        aFormatter->Print( aNestLevel+1, "(zone_connect %d)\n", aModule->m_ZoneConnection );
+
+    if( aModule->m_ThermalWidth != 0 )
+        aFormatter->Print( aNestLevel+1, "(thermal_width %s)\n",
+                           FMT_IU( aModule->m_ThermalWidth ).c_str() );
+
+    if( aModule->m_ThermalGap != 0 )
+        aFormatter->Print( aNestLevel+1, "(thermal_gap %s)\n",
+                           FMT_IU( aModule->m_ThermalGap ).c_str() );
+
+    // Attributes
+    if( aModule->m_Attributs != MOD_DEFAULT )
+    {
+        aFormatter->Print( aNestLevel+1, "(attr " );
+
+        if( aModule->m_Attributs & MOD_CMS )
+            aFormatter->Print( 0, " smd" );
+
+        if( aModule->m_Attributs & MOD_VIRTUAL )
+            aFormatter->Print( 0, " virtual" );
+
+        aFormatter->Print( 0, ")\n" );
+    }
+
+    Format( (BOARD_ITEM*) aModule->m_Reference, aFormatter, aNestLevel+1, aControlBits );
+    Format( (BOARD_ITEM*) aModule->m_Value, aFormatter, aNestLevel+1, aControlBits );
+
+    // Save drawing elements.
+    for( BOARD_ITEM* gr = aModule->m_Drawings;  gr;  gr = gr->Next() )
+        Format( gr, aFormatter, aNestLevel+1, aControlBits );
+
+    // Save pads.
+    for( D_PAD* pad = aModule->m_Pads;  pad;  pad = pad->Next() )
+        Format( pad, aFormatter, aNestLevel+1, aControlBits );
+
+    // Save 3D info.
+    for( S3D_MASTER* t3D = aModule->m_3D_Drawings;  t3D;  t3D = t3D->Next() )
+    {
+        if( !t3D->m_Shape3DName.IsEmpty() )
+        {
+            aFormatter->Print( aNestLevel+1, "(3d_shape %s\n",
+                               aFormatter->Quotew( t3D->m_Shape3DName ).c_str() );
+
+            aFormatter->Print( aNestLevel+2, "(at (xyz %.16g %.16g %.16g))\n",
+                               t3D->m_MatPosition.x,
+                               t3D->m_MatPosition.y,
+                               t3D->m_MatPosition.z );
+
+            aFormatter->Print( aNestLevel+2, "(scale (xyz %.16g %.16g %.16g))\n",
+                               t3D->m_MatScale.x,
+                               t3D->m_MatScale.y,
+                               t3D->m_MatScale.z );
+
+            aFormatter->Print( aNestLevel+2, "(rotate (xyz %.16g %.16g %.16g))\n",
+                               t3D->m_MatRotation.x,
+                               t3D->m_MatRotation.y,
+                               t3D->m_MatRotation.z );
+
+            aFormatter->Print( aNestLevel+1, ")\n" );
+        }
+    }
+
+    aFormatter->Print( aNestLevel, ")\n" );
+}
+
+
+
+
+void PCB_IO::format( D_PAD* aPad, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                     int aControlBits ) const
+    throw( IO_ERROR )
+{
+    std::string shape;
+
+    switch( aPad->GetShape() )
+    {
+    case PAD_CIRCLE:    shape = "circle";     break;
+    case PAD_RECT:      shape = "rectangle";  break;
+    case PAD_OVAL:      shape = "oval";       break;
+    case PAD_TRAPEZOID: shape = "trapezoid";  break;
+
+    default:
+        THROW_IO_ERROR( wxString::Format( _( "unknown pad type: %d"), aPad->GetShape() ) );
+    }
+
+    std::string type;
+
+    switch( aPad->GetAttribute() )
+    {
+    case PAD_STANDARD:          type = "thru_hole";      break;
+    case PAD_SMD:               type = "smd";            break;
+    case PAD_CONN:              type = "connect";        break;
+    case PAD_HOLE_NOT_PLATED:   type = "np_thru_hole";   break;
+
+    default:
+        THROW_IO_ERROR( wxString::Format( _( "unknown pad attribute: %d" ),
+                                          aPad->GetAttribute() ) );
+    }
+
+    aFormatter->Print( aNestLevel, "(pad %s %s %s (size %s)\n",
+                       aFormatter->Quotew( aPad->GetPadName() ).c_str(),
+                       type.c_str(), shape.c_str(),
+                       FMT_IU( aPad->GetSize() ).c_str() );
+    aFormatter->Print( aNestLevel+1, "(at %s", FMT_IU( aPad->GetPos0() ).c_str() );
+
+    if( aPad->GetOrientation() != 0.0 )
+        aFormatter->Print( 0, " %s", FMT_ANGLE( aPad->GetOrientation() ).c_str() );
+
+    aFormatter->Print( 0, ")\n" );
+
+    if( (aPad->GetDrillSize().GetWidth() > 0) || (aPad->GetDrillSize().GetHeight() > 0) )
+    {
+        std::string drill = (aPad->GetDrillSize().GetHeight() > 0) ?
+                            FMT_IU( aPad->GetDrillSize() ).c_str() :
+                            FMT_IU( aPad->GetDrillSize().GetWidth() ).c_str();
+        aFormatter->Print( aNestLevel+1, "(drill %s", drill.c_str() );
+
+        if( (aPad->GetOffset().x > 0) || (aPad->GetOffset().y > 0) )
+        {
+            std::string drillOffset = ( aPad->GetOffset().x > 0 ) ?
+                                      FMT_IU( aPad->GetOffset() ).c_str() :
+                                      FMT_IU( aPad->GetOffset().x ).c_str();
+            aFormatter->Print( 0, " (offset %s)", drillOffset.c_str() );
+        }
+
+        aFormatter->Print( 0, ")\n" );
+    }
+
+    aFormatter->Print( aNestLevel+1, "(layers %08X)\n", aPad->GetLayerMask() );
+
+    aFormatter->Print( aNestLevel+1, "(net %d %s)\n",
+                       aPad->GetNet(), aFormatter->Quotew( aPad->GetNetname() ).c_str() );
+
+    if( aPad->GetDieLength() != 0 )
+        aFormatter->Print( aNestLevel+1, "(die_length %s)\n",
+                           FMT_IU( aPad->GetDieLength() ).c_str() );
+
+    if( aPad->GetLocalSolderMaskMargin() != 0 )
+        aFormatter->Print( aNestLevel+1, "(solder_mask_margin %s)\n",
+                           FMT_IU( aPad->GetLocalSolderMaskMargin() ).c_str() );
+
+    if( aPad->GetLocalSolderPasteMargin() != 0 )
+        aFormatter->Print( aNestLevel+1, "(solder_paste_margin %s)\n",
+                           FMT_IU( aPad->GetLocalSolderPasteMargin() ).c_str() );
+
+    if( aPad->GetLocalSolderPasteMarginRatio() != 0 )
+        aFormatter->Print( aNestLevel+1, "(solder_paste_margin_ratio %g)\n",
+                           aPad->GetLocalSolderPasteMarginRatio() );
+
+    if( aPad->GetLocalClearance() != 0 )
+        aFormatter->Print( aNestLevel+1, "(clearance %s)\n",
+                           FMT_IU( aPad->GetLocalClearance() ).c_str() );
+
+    if( aPad->GetZoneConnection() != UNDEFINED_CONNECTION )
+        aFormatter->Print( aNestLevel+1, "(zone_connect %d)\n", aPad->GetZoneConnection() );
+
+    if( aPad->GetThermalWidth() != 0 )
+        aFormatter->Print( aNestLevel+1, "(thermal_width %s)\n",
+                           FMT_IU( aPad->GetThermalWidth() ).c_str() );
+
+    if( aPad->GetThermalGap() != 0 )
+        aFormatter->Print( aNestLevel+1, "(thermal_gap %s)\n",
+                           FMT_IU( aPad->GetThermalGap() ).c_str() );
+
+    aFormatter->Print( aNestLevel, ")\n" );
+}
+
+
+void PCB_IO::format( TEXTE_PCB* aText, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                     int aControlBits ) const
+    throw( IO_ERROR )
+{
+    aFormatter->Print( aNestLevel, "(gr_text %s (at %s %s) (layer %s)",
+                       aFormatter->Quotew( aText->GetText() ).c_str(),
+                       FMT_IU( aText->GetPosition() ).c_str(),
+                       FMT_ANGLE( aText->GetOrientation() ).c_str(),
+                       aFormatter->Quotew( aText->GetLayerName() ).c_str() );
+
+    if( aText->GetTimeStamp() )
+        aFormatter->Print( 0, " (tstamp %lX)", aText->GetTimeStamp() );
+
+    aFormatter->Print( 0, "\n" );
+
+    aText->EDA_TEXT::Format( aFormatter, aNestLevel, aControlBits );
+
+    aFormatter->Print( aNestLevel, ")\n" );
+}
+
+
+void PCB_IO::format( TEXTE_MODULE* aText, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                     int aControlBits ) const
+    throw( IO_ERROR )
+{
+    MODULE*  parent = (MODULE*) aText->GetParent();
+    double   orient = aText->GetOrientation();
+    wxString type;
+
+    switch( aText->GetType() )
+    {
+    case 0:      type = wxT( "reference" );     break;
+    case 1:      type = wxT( "value" );         break;
+    default:     type = wxT( "user" );
+    }
+
+    // Due to the Pcbnew history, m_Orient is saved in screen value
+    // but it is handled as relative to its parent footprint
+    if( parent )
+        orient += parent->GetOrientation();
+
+    aFormatter->Print( aNestLevel, "(fp_text %s %s (at %s %s)%s\n",
+                       aFormatter->Quotew( type ).c_str(),
+                       aFormatter->Quotew( aText->GetText() ).c_str(),
+                       FMT_IU( aText->GetPos0() ).c_str(), FMT_ANGLE( orient ).c_str(),
+                       (!aText->IsVisible()) ? " hide" : "" );
+
+    aText->EDA_TEXT::Format( aFormatter, aNestLevel, aControlBits );
+
+    aFormatter->Print( aNestLevel, ")\n" );
+}
+
+
+void PCB_IO::format( TRACK* aTrack, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                     int aControlBits ) const
+    throw( IO_ERROR )
+{
+    if( aTrack->Type() == PCB_VIA_T )
+    {
+        std::string type;
+        int layer1, layer2;
+
+        SEGVIA* via = (SEGVIA*) aTrack;
+        BOARD* board = (BOARD*) via->GetParent();
+
+        wxCHECK_RET( board != 0, wxT( "Via " ) + via->GetSelectMenuText() +
+                     wxT( " has no parent." ) );
+
+        via->ReturnLayerPair( &layer1, &layer2 );
+
+        switch( aTrack->GetShape() )
+        {
+        case VIA_THROUGH:       type = "thru";     break;
+        case VIA_BLIND_BURIED:  type = "blind";    break;
+        case VIA_MICROVIA:      type = "micro";    break;
+        default:
+            THROW_IO_ERROR( wxString::Format( _( "unknown via type %d"  ), aTrack->GetShape() ) );
+        }
+
+        aFormatter->Print( aNestLevel, "(via %s (at %s) (size %s)", type.c_str(),
+                           FMT_IU( aTrack->GetStart() ).c_str(),
+                           FMT_IU( aTrack->GetWidth() ).c_str() );
+
+        if( aTrack->GetDrill() != UNDEFINED_DRILL_DIAMETER )
+            aFormatter->Print( 0, " (drill %s)", FMT_IU( aTrack->GetDrill() ).c_str() );
+
+        aFormatter->Print( 0, " (layers %s %s) (net %d)",
+                           aFormatter->Quotew( board->GetLayerName( layer1 ) ).c_str(),
+                           aFormatter->Quotew( board->GetLayerName( layer2 ) ).c_str(),
+                           aTrack->GetNet() );
+    }
+    else
+    {
+        aFormatter->Print( aNestLevel, "(segment (start %s) (end %s) (width %s)",
+                           FMT_IU( aTrack->GetStart() ).c_str(), FMT_IU( aTrack->GetEnd() ).c_str(),
+                           FMT_IU( aTrack->GetWidth() ).c_str() );
+
+        aFormatter->Print( 0, " (layer %s) (net %d)",
+                           aFormatter->Quotew( aTrack->GetLayerName() ).c_str(),
+                           aTrack->GetNet() );
+    }
+
+    if( aTrack->GetTimeStamp() != 0 )
+        aFormatter->Print( 0, " (tstamp %lX)", aTrack->GetTimeStamp() );
+
+    if( aTrack->GetStatus() != 0 )
+        aFormatter->Print( 0, " (status %X)", aTrack->GetStatus() );
+
+    aFormatter->Print( 0, ")\n" );
+}
+
+
+void PCB_IO::format( ZONE_CONTAINER* aZone, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                     int aControlBits ) const
+    throw( IO_ERROR )
+{
+    aFormatter->Print( aNestLevel, "(zone (net %d %s) (layer %s) (tstamp %lX)\n",
+                       aZone->GetNet(), aFormatter->Quotew( aZone->GetNetName() ).c_str(),
+                       aFormatter->Quotew( aZone->GetLayerName() ).c_str(),
+                       aZone->GetTimeStamp() );
+
+
+    // Save the outline aux info
+    std::string hatch;
+
+    switch( aZone->GetHatchStyle() )
+    {
+    default:
+    case CPolyLine::NO_HATCH:       hatch = "none";    break;
+    case CPolyLine::DIAGONAL_EDGE:  hatch = "edge";    break;
+    case CPolyLine::DIAGONAL_FULL:  hatch = "full";    break;
+    }
+
+    aFormatter->Print( aNestLevel+1, "(hatch %s)\n", hatch.c_str() );
+
+    if( aZone->GetPriority() > 0 )
+        aFormatter->Print( aNestLevel+1, "(priority %d)\n", aZone->GetPriority() );
+
+    // Save pad option and clearance
+    std::string padoption;
+
+    switch( aZone->GetPadConnection() )
+    {
+    default:
+    case PAD_IN_ZONE:       padoption = "yes";          break;
+    case THERMAL_PAD:       padoption = "use_thermal";  break;
+    case PAD_NOT_IN_ZONE:   padoption = "no";           break;
+    }
+
+    aFormatter->Print( aNestLevel+1, "(connect_pads %s (clearance %s))\n",
+                       padoption.c_str(), FMT_IU( aZone->GetZoneClearance() ).c_str() );
+
+    aFormatter->Print( aNestLevel+1, "(min_thickness %s)\n",
+                       FMT_IU( aZone->GetMinThickness() ).c_str() );
+
+    aFormatter->Print( aNestLevel+1,
+                       "(fill %s (mode %s) (arc_segments %d) (thermal_gap %s) (thermal_bridge_width %s)\n",
+                       (aZone->IsFilled()) ? "yes" : "no",
+                       (aZone->GetFillMode()) ? "segment" : "polygon",
+                       aZone->m_ArcToSegmentsCount,
+                       FMT_IU( aZone->GetThermalReliefGap() ).c_str(),
+                       FMT_IU( aZone->GetThermalReliefCopperBridge() ).c_str() );
+
+    std::string smoothing;
+
+    switch( aZone->GetCornerSmoothingType() )
+    {
+    case ZONE_SETTINGS::SMOOTHING_NONE:      smoothing = "none";      break;
+    case ZONE_SETTINGS::SMOOTHING_CHAMFER:   smoothing = "chamfer";   break;
+    case ZONE_SETTINGS::SMOOTHING_FILLET:    smoothing = "fillet";    break;
+    default:
+        THROW_IO_ERROR( wxString::Format( _( "unknown zone corner smoothing type %d"  ),
+                                          aZone->GetCornerSmoothingType() ) );
+    }
+
+    aFormatter->Print( aNestLevel+1, "(smoothing %s (radius %s))\n",
+                       smoothing.c_str(), FMT_IU( aZone->GetCornerRadius() ).c_str() );
+
+    const std::vector< CPolyPt >& cv = aZone->m_Poly->corner;
+
+    if( cv.size() )
+    {
+        aFormatter->Print( aNestLevel+1, "(polygon\n");
+        aFormatter->Print( aNestLevel+2, "(pts\n" );
+
+        for( std::vector< CPolyPt >::const_iterator it = cv.begin();  it != cv.end();  ++it )
+        {
+            aFormatter->Print( aNestLevel+3, "(xy %s %s)\n",
+                               FMT_IU( it->x ).c_str(), FMT_IU( it->y ).c_str() );
+
+            if( it->end_contour )
+            {
+                aFormatter->Print( aNestLevel+2, ")\n" );
+
+                if( it+1 != cv.end() )
+                {
+                    aFormatter->Print( aNestLevel+1, ")\n" );
+                    aFormatter->Print( aNestLevel+1, "(polygon\n" );
+                    aFormatter->Print( aNestLevel+2, "(pts\n" );
+                }
+            }
+        }
+
+        aFormatter->Print( aNestLevel+1, ")\n" );
+    }
+
+    // Save the PolysList
+    const std::vector< CPolyPt >& fv = aZone->m_FilledPolysList;
+
+    if( fv.size() )
+    {
+        aFormatter->Print( aNestLevel+1, "(filled_polygon\n" );
+        aFormatter->Print( aNestLevel+2, "(pts\n" );
+
+        for( std::vector< CPolyPt >::const_iterator it = fv.begin();  it != fv.end();  ++it )
+        {
+            aFormatter->Print( aNestLevel+3, "(xy %s %s)\n",
+                               FMT_IU( it->x ).c_str(), FMT_IU( it->y ).c_str() );
+
+            if( it->end_contour )
+            {
+                aFormatter->Print( aNestLevel+2, ")\n" );
+
+                if( it+1 != fv.end() )
+                {
+                    aFormatter->Print( aNestLevel+1, ")\n" );
+                    aFormatter->Print( aNestLevel+1, "(filled_polygon\n" );
+                    aFormatter->Print( aNestLevel+2, "(pts\n" );
+                }
+            }
+        }
+
+        aFormatter->Print( aNestLevel+1, ")\n" );
+    }
+
+    // Save the filling segments list
+    const std::vector< SEGMENT >& segs = aZone->m_FillSegmList;
+
+    if( segs.size() )
+    {
+        aFormatter->Print( aNestLevel+1, "(fill_segments\n" );
+
+        for( std::vector< SEGMENT >::const_iterator it = segs.begin();  it != segs.end();  ++it )
+        {
+            aFormatter->Print( aNestLevel+2, "(pts (xy %s) (xy %s))\n",
+                               FMT_IU( it->m_Start ).c_str(),
+                               FMT_IU( it->m_End ).c_str() );
+        }
+
+        aFormatter->Print( aNestLevel+1, ")\n" );
+    }
+
+    aFormatter->Print( aNestLevel, ")\n" );
+}
diff --git a/pcbnew/kicad_plugin.h b/pcbnew/kicad_plugin.h
index 89dd49c56a..8805066bf5 100644
--- a/pcbnew/kicad_plugin.h
+++ b/pcbnew/kicad_plugin.h
@@ -27,17 +27,24 @@
 #include <io_mgr.h>
 #include <string>
 
+class BOARD;
+class BOARD_ITEM;
+
+
 /** Current s-expression file format version.  2 was the last legacy format version. */
 #define SEXPR_BOARD_FILE_VERSION   3
 
+/** Format output for the clipboard instead of a file. */
+#define CTL_CLIPBOARD              (1 << 0)
+
 
 /**
- * Class KICAD_PLUGIN
+ * Class PCB_IO
  * is a PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
  *
  * @note This class is not thread safe, but it is re-entrant multiple times in sequence.
  */
-class KICAD_PLUGIN : public PLUGIN
+class PCB_IO : public PLUGIN
 {
 
 public:
@@ -49,13 +56,27 @@ public:
 
     const wxString& GetFileExtension() const
     {
-        static const wxString extension = wxT( "kicad_brd" );
+        static const wxString extension = wxT( "kicad_pcb" );
         return extension;
     }
 
     void Save( const wxString& aFileName, BOARD* aBoard,
                PROPERTIES* aProperties = NULL );          // overload
 
+    /**
+     * Function Format
+     * outputs \a aItem to \a aFormatter in s-expression format.
+     *
+     * @param aItem A pointer the an #BOARD_ITEM object to format.
+     * @param aFormatter The #OUTPUTFORMATTER object to write to.
+     * @param aNestLevel The indentation nest level.
+     * @param aControlBits The control bit definition for object specific formatting.
+     * @throw IO_ERROR on write error.
+     */
+    void Format( BOARD_ITEM* aItem, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                 int aControlBits ) const
+        throw( IO_ERROR );
+
 protected:
 
     wxString        m_error;        ///< for throwing exceptions
@@ -66,6 +87,51 @@ protected:
     wxString        m_filename;     ///< for saves only, name is in m_reader for loads
 
     int             m_loading_format_version;   ///< which BOARD_FORMAT_VERSION am I Load()ing?
+
+private:
+    void format( BOARD* aBoard, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                 int aControlBits ) const
+        throw( IO_ERROR );
+
+    void format( DIMENSION* aDimension, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                 int aControlBits ) const
+        throw( IO_ERROR );
+
+    void format( EDGE_MODULE* aModuleDrawing, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                 int aControlBits ) const
+        throw( IO_ERROR );
+
+    void format( DRAWSEGMENT* aSegment, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                 int aControlBits ) const
+        throw( IO_ERROR );
+
+    void format( PCB_TARGET* aTarget, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                         int aControlBits ) const
+        throw( IO_ERROR );
+
+    void format( MODULE* aModule, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                 int aControlBits ) const
+        throw( IO_ERROR );
+
+    void format( D_PAD* aPad, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                 int aControlBits ) const
+        throw( IO_ERROR );
+
+    void format( TEXTE_PCB* aText, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                 int aControlBits ) const
+        throw( IO_ERROR );
+
+    void format( TEXTE_MODULE* aText, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                 int aControlBits ) const
+        throw( IO_ERROR );
+
+    void format( TRACK* aTrack, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                 int aControlBits ) const
+        throw( IO_ERROR );
+
+    void format( ZONE_CONTAINER* aZone, OUTPUTFORMATTER* aFormatter, int aNestLevel,
+                 int aControlBits ) const
+        throw( IO_ERROR );
 };
 
 #endif  // KICAD_PLUGIN_H_