diff --git a/common/fp_lib_table.cpp b/common/fp_lib_table.cpp
index d4f8500b50..95e20b8a62 100644
--- a/common/fp_lib_table.cpp
+++ b/common/fp_lib_table.cpp
@@ -142,6 +142,9 @@ void FP_LIB_TABLE::Parse( FP_LIB_TABLE_LEXER* in ) throw( IO_ERROR, PARSE_ERROR
                 sawOpts = true;
                 in->NeedSYMBOLorNUMBER();
                 row.SetOptions( in->FromUTF8() );
+
+                // create PROPERTIES* from options, set into the ROW
+                row.properties = ParseOptions( in->CurText() );
                 break;
 
             case T_descr:
@@ -205,6 +208,101 @@ void FP_LIB_TABLE::ROW::Format( OUTPUTFORMATTER* out, int nestLevel ) const
 }
 
 
+#define OPT_SEP     '|'         ///< options separator character
+
+PROPERTIES* FP_LIB_TABLE::ParseOptions( const std::string& aOptionsList )
+{
+    const char* cp  = &aOptionsList[0];
+    const char* end = cp + aOptionsList.size();
+
+    PROPERTIES  props;
+    std::string pair;
+
+    // Parse all name=value pairs
+    while( cp < end )
+    {
+        pair.clear();
+
+        // Skip leading white space.
+        while( cp < end && isspace( *cp )  )
+            ++cp;
+
+        // Find the end of pair/field
+        while( cp<end )
+        {
+            if( *cp == '\\' && cp+1 < end && cp[1]==OPT_SEP  )
+            {
+                ++cp;           // skip the escape
+                pair += *cp++;  // add the separator
+            }
+
+            else if( *cp==OPT_SEP )
+            {
+                ++cp;           // skip the separator
+                break;          // process the pair
+            }
+            else
+                pair += *cp++;
+        }
+
+        // stash the pair
+        if( pair.size() )
+        {
+            // the first equals size established the end of the name
+            size_t  eqNdx = pair.find( '=' );
+            if( eqNdx != pair.npos )
+            {
+                std::string name  = pair.substr( 0, eqNdx );
+                std::string value = pair.substr( eqNdx + 1 );
+                props[name] = value;
+            }
+            else
+                props[pair] = "";
+        }
+    }
+
+    if( props.size() )
+        return new PROPERTIES( props );
+    else
+        return NULL;
+}
+
+
+std::string FP_LIB_TABLE::FormatOptions( const PROPERTIES* aProperties )
+{
+    std::string ret;
+
+    if( aProperties )
+    {
+        for( PROPERTIES::const_iterator it = aProperties->begin();  it != aProperties->end(); ++it )
+        {
+            const std::string& name  = it->first;
+            const std::string& value = it->second;
+
+            if( ret.size() )
+                ret += OPT_SEP;
+
+            ret += name;
+
+            // the separation between name and value is '='
+            if( value.size() )
+                ret += '=';
+
+            for( std::string::const_iterator si = value.begin();  si != value.end();  ++si )
+            {
+                // escape any separator in the value.
+                if( *si == OPT_SEP )
+                    ret += '\\';
+
+                ret += *si;
+            }
+        }
+    }
+
+    return ret;
+}
+
+
 std::vector<wxString> FP_LIB_TABLE::GetLogicalLibs()
 {
     // Only return unique logical library names.  Use std::set::insert() to
diff --git a/include/fp_lib_table.h b/include/fp_lib_table.h
index 1ac53c7576..c23fd4609e 100644
--- a/include/fp_lib_table.h
+++ b/include/fp_lib_table.h
@@ -103,7 +103,9 @@ public:
 
         typedef IO_MGR::PCB_FILE_T   LIB_T;
 
-        ROW() : type( IO_MGR::KICAD )
+        ROW() :
+            type( IO_MGR::KICAD ),
+            properties( 0 )
         {
         }
 
@@ -112,11 +114,39 @@ public:
             nickName( aNick ),
             uri( aURI ),
             options( aOptions ),
-            description( aDescr )
+            description( aDescr ),
+            properties( 0 )
         {
             SetType( aType );
         }
 
+        ROW( const ROW& a ) :
+            nickName( a.nickName ),
+            uri( a.uri ),
+            type( a.type ),
+            options( a.options ),
+            description( a.description ),
+            properties( 0 )
+        {
+            if( a.properties )
+                properties = new PROPERTIES( *a.properties );
+        }
+
+        ~ROW()
+        {
+            delete properties;
+        }
+
+        ROW& operator=( const ROW& r )
+        {
+            nickName = r.nickName;
+            uri      = r.uri;
+            type     = r.type;
+            options  = r.options;
+            properties = r.properties ? new PROPERTIES( *r.properties ) : NULL;
+            return *this;
+        }
+
         bool operator==( const ROW& r ) const
         {
             return  nickName==r.nickName && uri==r.uri && type==r.type && options==r.options;
@@ -206,6 +236,7 @@ public:
         LIB_T           type;
         wxString        options;
         wxString        description;
+        PROPERTIES*     properties;
     };
 
 
@@ -261,6 +292,31 @@ public:
      */
     void Parse( FP_LIB_TABLE_LEXER* aParser ) throw( IO_ERROR, PARSE_ERROR );
 
+    /**
+     * Function ParseOptions
+     * parses @a aOptionsList and places the result into a PROPERTIES object
+     * which is returned.  If the options field is empty, then the returned PROPERTIES
+     * will be a NULL pointer.
+     * <p>
+     * Typically aOptionsList comes from the "options" field within a ROW and
+     * the format is simply a comma separated list of name value pairs. e.g.:
+     * [name1[=value1][|name2[=value2]]] etc.  When using the UI to create or edit
+     * a fp lib table, this formatting is handled for you.
+     */
+    static PROPERTIES* ParseOptions( const std::string& aOptionsList );
+
+    /**
+     * Function FormatOptions
+     * returns a list of options from the aProperties parameter.  The name=value
+     * pairs will be separted with the '|' character.  The =value portion may not
+     * be present.  You might expect something like "name1=value1|name2=value2|flag_me".
+     * Notice that flag_me does not have a value.  This is ok.
+     *
+     * @param aProperties is the PROPERTIES to format or NULL.  If NULL the returned
+     *  string will be empty.
+     */
+    static std::string FormatOptions( const PROPERTIES* aProperties );
+
     /**
      * Function Format
      * serializes this object as utf8 text to an #OUTPUTFORMATTER, and tries to
@@ -272,7 +328,6 @@ public:
      */
     void Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IO_ERROR );
 
-
     /**
      * Function GetLogicalLibs
      * returns the logical library names, all of them that are pertinent to
@@ -280,8 +335,6 @@ public:
      */
     std::vector<wxString> GetLogicalLibs();
 
-
-
     //----<read accessors>----------------------------------------------------
     // the returning of a const wxString* tells if not found, but might be too
     // promiscuous?
@@ -480,7 +533,7 @@ protected:
     typedef ROWS::iterator              ROWS_ITER;
     typedef ROWS::const_iterator        ROWS_CITER;
 
-    ROWS           rows;
+    ROWS            rows;
 
     /// this is a non-owning index into the ROWS table
     typedef std::map<wxString,int>      INDEX;              // "int" is std::vector array index
@@ -491,7 +544,7 @@ protected:
     /// this particular key is the nickName within each row.
     INDEX           nickIndex;
 
-    FP_LIB_TABLE*  fallBack;
+    FP_LIB_TABLE*   fallBack;
 };
 
 
diff --git a/include/hashtables.h b/include/hashtables.h
index 2523baa057..d117a59abc 100644
--- a/include/hashtables.h
+++ b/include/hashtables.h
@@ -37,14 +37,14 @@
 #include <unordered_map>
 
 /// Map a C string to a wxString, used in PLUGINs.
-typedef std::unordered_map< std::string, wxString >  PROPERTIES;
+typedef std::unordered_map< std::string, std::string >  PROPERTIES;
 
 /// Map a C string to an integer.  Used in DSNLEXER.
-typedef std::unordered_map< std::string, int >       KEYWORD_MAP;
+typedef std::unordered_map< std::string, int >          KEYWORD_MAP;
 
 /// Map a C string to an EDA_RECT.
 /// The key is the classname of the derived wxformbuilder dialog.
-typedef std::unordered_map< std::string, EDA_RECT >  RECT_MAP;
+typedef std::unordered_map< std::string, EDA_RECT >     RECT_MAP;
 
 
 #elif 1     // boost::unordered_map
@@ -57,7 +57,7 @@ typedef std::unordered_map< std::string, EDA_RECT >  RECT_MAP;
 // see http://www.boost.org/doc/libs/1_49_0/doc/html/boost/unordered_map.html
 
 /// Map a std::string to a wxString, used in PLUGINs.
-typedef boost::unordered_map< std::string, wxString >  PROPERTIES;
+typedef boost::unordered_map< std::string, std::string >    PROPERTIES;
 
 
 /// Equality test for "const char*" type used in very specialized KEYWORD_MAP below
diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt
index cf7b8f9804..7aa7cfaeb4 100644
--- a/pcbnew/CMakeLists.txt
+++ b/pcbnew/CMakeLists.txt
@@ -1,3 +1,6 @@
+
+set( MAKE_LINK_MAPS true )
+
 add_definitions( -DPCBNEW )
 
 if( KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES )
@@ -322,7 +325,6 @@ endif()
 # _pcbnew DLL/DSO file creation
 ###
 
-unset( GITHUB_PLUGIN_LIBRARIES )
 if( BUILD_GITHUB_PLUGIN )
     set( GITHUB_PLUGIN_LIBRARIES github_plugin )
 endif()
@@ -362,6 +364,11 @@ if( KICAD_SCRIPTING_MODULES )
         WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/scripting/qa
         )
 
+    if( MAKE_LINK_MAPS )
+        # generate a link map with cross reference
+        set_target_properties( _pcbnew PROPERTIES LINK_FLAGS "-Wl,-cref -Wl,-Map=_pcbnew.map" )
+    endif()
+
 endif()
 
 
@@ -507,6 +514,7 @@ target_link_libraries( pcbnew
     pcad2kicadpcb
     polygon
     bitmaps
+    ${GITHUB_PLUGIN_LIBRARIES}
     ${wxWidgets_LIBRARIES}
     ${OPENGL_LIBRARIES}
     ${GDI_PLUS_LIBRARIES}
@@ -514,8 +522,10 @@ target_link_libraries( pcbnew
     ${PCBNEW_EXTRA_LIBS}
     )
 
-if( BUILD_GITHUB_PLUGIN )
-    target_link_libraries( pcbnew github_plugin )
+
+if( MAKE_LINK_MAPS )
+    # generate a link map with cross reference
+    set_target_properties( pcbnew PROPERTIES LINK_FLAGS "-Wl,-cref -Wl,-Map=pcbnew.map" )
 endif()
 
 
diff --git a/pcbnew/dialogs/dialog_fp_lib_table.cpp b/pcbnew/dialogs/dialog_fp_lib_table.cpp
index e3886b0628..29a1aaf2a5 100644
--- a/pcbnew/dialogs/dialog_fp_lib_table.cpp
+++ b/pcbnew/dialogs/dialog_fp_lib_table.cpp
@@ -48,6 +48,19 @@
 #include <wx/regex.h>
 #include <set>
 
+
+/// grid column order is established by this sequence
+enum COL_ORDER
+{
+    COL_NICKNAME,
+    COL_URI,
+    COL_TYPE,
+    COL_OPTIONS,
+    COL_DESCR,
+    COL_COUNT       // keep as last
+};
+
+
 /**
  * Class FP_TBL_MODEL
  * mixes in wxGridTableBase into FP_LIB_TABLE so that the latter can be used
@@ -57,16 +70,6 @@ class FP_TBL_MODEL : public wxGridTableBase, public FP_LIB_TABLE
 {
 public:
 
-    enum COL_ORDER      ///<  grid column order, established by this sequence
-    {
-        COL_NICKNAME,
-        COL_URI,
-        COL_TYPE,
-        COL_OPTIONS,
-        COL_DESCR,
-        COL_COUNT       // keep as last
-    };
-
     /**
      * Constructor FP_TBL_MODEL
      * is a copy constructor that builds a wxGridTableBase (table model) by wrapping
@@ -79,8 +82,8 @@ public:
 
     //-----<wxGridTableBase overloads>-------------------------------------------
 
-    int         GetNumberRows () { return rows.size(); }
-    int         GetNumberCols () { return COL_COUNT; }
+    int         GetNumberRows()     { return rows.size(); }
+    int         GetNumberCols()     { return COL_COUNT; }
 
     wxString    GetValue( int aRow, int aCol )
     {
@@ -394,6 +397,102 @@ class DIALOG_FP_LIB_TABLE : public DIALOG_FP_LIB_TABLE_BASE
         }
     }
 
+    /**
+     * Function verifyTables
+     * trims important fields, removes blank row entries, and checks for duplicates.
+     * @return bool - true if tables are OK, else false.
+     */
+    bool verifyTables()
+    {
+        for( int t=0; t<2; ++t )
+        {
+            FP_TBL_MODEL& model = t==0 ? m_global_model : m_project_model;
+
+            for( int r = 0; r < model.GetNumberRows(); )
+            {
+                wxString nick = model.GetValue( r, COL_NICKNAME ).Trim( false ).Trim();
+                wxString uri  = model.GetValue( r, COL_URI ).Trim( false ).Trim();
+                wxString type = model.GetValue( r, COL_TYPE ).Trim( false ).Trim();
+
+                if( !nick || !uri || !type )
+                {
+                    // Delete the "empty" row, where empty means missing nick, uri, or type.
+                    // This also updates the UI which could be slow, but there should only be a few
+                    // rows to delete, unless the user fell asleep on the Add Row
+                    // button.
+                    model.DeleteRows( r, 1 );
+                }
+                else if( nick.find(':') != size_t(-1) )
+                {
+                    wxString msg = wxString::Format(
+                        _( "Illegal character '%s' found in Nickname: '%s' in row %d" ),
+                        wxT( ":" ), GetChars( nick ), r );
+
+                    // show the tabbed panel holding the grid we have flunked:
+                    if( &model != (FP_TBL_MODEL*) m_cur_grid->GetTable() )
+                    {
+                        m_auinotebook->SetSelection( &model == &m_global_model ? 0 : 1 );
+                    }
+
+                    // go to the bottom of the two rows, it is technically the duplicate:
+                    m_cur_grid->SelectBlock( r, 0, r, 0 );
+                    m_cur_grid->MakeCellVisible( r, 0 );
+
+                    wxMessageDialog errdlg( this, msg, _( "No Colon in Nicknames" ) );
+                    errdlg.ShowModal();
+                    return false;
+                }
+                else
+                {
+                    // set the trimmed values back into the table so they get saved to disk.
+                    model.SetValue( r, COL_NICKNAME, nick );
+                    model.SetValue( r, COL_URI, uri );
+                    model.SetValue( r, COL_TYPE, type );
+                    ++r;        // this row was OK.
+                }
+            }
+        }
+
+        // check for duplicate nickNames, separately in each table.
+        for( int t=0; t<2; ++t )
+        {
+            FP_TBL_MODEL& model = t==0 ? m_global_model : m_project_model;
+
+            for( int r1 = 0; r1 < model.GetNumberRows() - 1;  ++r1 )
+            {
+                for( int r2=r1+1; r2 < model.GetNumberRows();  ++r2 )
+                {
+                    wxString    nick1 = model.GetValue( r1, COL_NICKNAME );
+                    wxString    nick2 = model.GetValue( r2, COL_NICKNAME );
+
+                    if( nick1 == nick2 )
+                    {
+                        wxString msg = wxString::Format(
+                            _( "Duplicate Nickname: '%s' in rows %d and %d" ),
+                            GetChars( nick1 ), r1+1, r2+1
+                            );
+
+                        // show the tabbed panel holding the grid we have flunked:
+                        if( &model != (FP_TBL_MODEL*) m_cur_grid->GetTable() )
+                        {
+                            m_auinotebook->SetSelection( &model == &m_global_model ? 0 : 1 );
+                        }
+
+                        // go to the bottom of the two rows, it is technically the duplicate:
+                        m_cur_grid->SelectBlock( r2, 0, r2, 0 );
+                        m_cur_grid->MakeCellVisible( r2, 0 );
+
+                        wxMessageDialog errdlg( this, msg, _( "Please Delete or Modify One" ) );
+                        errdlg.ShowModal();
+                        return false;
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
+
     //-----<event handlers>----------------------------------
 
     void pageChangedHandler( wxAuiNotebookEvent& event )
@@ -404,7 +503,13 @@ class DIALOG_FP_LIB_TABLE : public DIALOG_FP_LIB_TABLE_BASE
 
     void appendRowHandler( wxMouseEvent& event )
     {
-        m_cur_grid->AppendRows( 1 );
+        if( m_cur_grid->AppendRows( 1 ) )
+        {
+            int last_row = m_cur_grid->GetNumberRows() - 1;
+
+            m_cur_grid->SelectBlock( last_row, 0, last_row, 0 );
+            m_cur_grid->MakeCellVisible( last_row, 0 );
+        }
     }
 
     void deleteRowHandler( wxMouseEvent& event )
@@ -474,6 +579,12 @@ class DIALOG_FP_LIB_TABLE : public DIALOG_FP_LIB_TABLE_BASE
         D(printf("%s\n", __func__);)
     }
 
+    void optionsEditor( wxMouseEvent& event )
+    {
+        // @todo: write the options editor, and pass the options to the Footprint*() calls.
+        D(printf("%s:%d\n", __func__, (int) m_cur_grid->GetRowCount() );)
+    }
+
     void onCancelButtonClick( wxCommandEvent& event )
     {
         EndModal( 0 );
@@ -483,23 +594,26 @@ class DIALOG_FP_LIB_TABLE : public DIALOG_FP_LIB_TABLE_BASE
     {
         int dialogRet = 0;
 
-        if( m_global_model != *m_global )
+        if( verifyTables() )
         {
-            dialogRet |= 1;
+            if( m_global_model != *m_global )
+            {
+                dialogRet |= 1;
 
-            *m_global  = m_global_model;
-            m_global->reindex();
+                *m_global  = m_global_model;
+                m_global->reindex();
+            }
+
+            if( m_project_model != *m_project )
+            {
+                dialogRet |= 2;
+
+                *m_project = m_project_model;
+                m_project->reindex();
+            }
+
+            EndModal( dialogRet );
         }
-
-        if( m_project_model != *m_project )
-        {
-            dialogRet |= 2;
-
-            *m_project = m_project_model;
-            m_project->reindex();
-        }
-
-        EndModal( dialogRet );
     }
 
     void onGridCellLeftClick( wxGridEvent& event )
@@ -546,7 +660,7 @@ class DIALOG_FP_LIB_TABLE : public DIALOG_FP_LIB_TABLE_BASE
 
         for( row = 0;  row < gblRowCount;  ++row )
         {
-            wxString uri = m_global_model.GetValue( row, FP_TBL_MODEL::COL_URI );
+            wxString uri = m_global_model.GetValue( row, COL_URI );
 
             while( re.Matches( uri ) )
             {
@@ -562,7 +676,7 @@ class DIALOG_FP_LIB_TABLE : public DIALOG_FP_LIB_TABLE_BASE
 
         for( row = 0;  row < prjRowCount;  ++row )
         {
-            wxString uri = m_project_model.GetValue( row, FP_TBL_MODEL::COL_URI );
+            wxString uri = m_project_model.GetValue( row, COL_URI );
 
             while( re.Matches( uri ) )
             {
@@ -643,11 +757,11 @@ public:
 
         attr = new wxGridCellAttr;
         attr->SetEditor( new wxGridCellChoiceEditor( choices ) );
-        m_project_grid->SetColAttr( FP_TBL_MODEL::COL_TYPE, attr );
+        m_project_grid->SetColAttr( COL_TYPE, attr );
 
         attr = new wxGridCellAttr;
         attr->SetEditor( new wxGridCellChoiceEditor( choices ) );
-        m_global_grid->SetColAttr(  FP_TBL_MODEL::COL_TYPE, attr );
+        m_global_grid->SetColAttr( COL_TYPE, attr );
 
         m_global_grid->AutoSizeColumns();
         m_project_grid->AutoSizeColumns();
@@ -688,4 +802,3 @@ int InvokePcbLibTableEditor( wxFrame* aParent, FP_LIB_TABLE* aGlobal, FP_LIB_TAB
 
     return dialogRet;
 }
-
diff --git a/pcbnew/dialogs/dialog_fp_lib_table_base.cpp b/pcbnew/dialogs/dialog_fp_lib_table_base.cpp
index c392d8c018..01bc85152f 100644
--- a/pcbnew/dialogs/dialog_fp_lib_table_base.cpp
+++ b/pcbnew/dialogs/dialog_fp_lib_table_base.cpp
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Oct  8 2012)
+// C++ code generated with wxFormBuilder (version Apr 30 2013)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO "NOT" EDIT THIS FILE!
@@ -127,6 +127,11 @@ DIALOG_FP_LIB_TABLE_BASE::DIALOG_FP_LIB_TABLE_BASE( wxWindow* parent, wxWindowID
 	
 	bSizer51->Add( m_move_down_button, 0, wxALL, 5 );
 	
+	m_edit_options = new wxButton( m_top, wxID_ANY, _("Options Editor"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_edit_options->SetToolTip( _("Zoom into the options table for current row") );
+	
+	bSizer51->Add( m_edit_options, 0, wxALL, 5 );
+	
 	
 	m_top_sizer->Add( bSizer51, 0, wxALIGN_CENTER|wxBOTTOM, 8 );
 	
@@ -211,6 +216,7 @@ DIALOG_FP_LIB_TABLE_BASE::DIALOG_FP_LIB_TABLE_BASE( wxWindow* parent, wxWindowID
 	m_delete_button->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DIALOG_FP_LIB_TABLE_BASE::deleteRowHandler ), NULL, this );
 	m_move_up_button->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DIALOG_FP_LIB_TABLE_BASE::moveUpHandler ), NULL, this );
 	m_move_down_button->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DIALOG_FP_LIB_TABLE_BASE::moveDownHandler ), NULL, this );
+	m_edit_options->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DIALOG_FP_LIB_TABLE_BASE::optionsEditor ), NULL, this );
 	m_sdbSizer1Cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FP_LIB_TABLE_BASE::onCancelButtonClick ), NULL, this );
 	m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FP_LIB_TABLE_BASE::onOKButtonClick ), NULL, this );
 }
@@ -231,6 +237,7 @@ DIALOG_FP_LIB_TABLE_BASE::~DIALOG_FP_LIB_TABLE_BASE()
 	m_delete_button->Disconnect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DIALOG_FP_LIB_TABLE_BASE::deleteRowHandler ), NULL, this );
 	m_move_up_button->Disconnect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DIALOG_FP_LIB_TABLE_BASE::moveUpHandler ), NULL, this );
 	m_move_down_button->Disconnect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DIALOG_FP_LIB_TABLE_BASE::moveDownHandler ), NULL, this );
+	m_edit_options->Disconnect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DIALOG_FP_LIB_TABLE_BASE::optionsEditor ), NULL, this );
 	m_sdbSizer1Cancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FP_LIB_TABLE_BASE::onCancelButtonClick ), NULL, this );
 	m_sdbSizer1OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FP_LIB_TABLE_BASE::onOKButtonClick ), NULL, this );
 	
diff --git a/pcbnew/dialogs/dialog_fp_lib_table_base.fbp b/pcbnew/dialogs/dialog_fp_lib_table_base.fbp
index c2ad44dfee..aea158009e 100644
--- a/pcbnew/dialogs/dialog_fp_lib_table_base.fbp
+++ b/pcbnew/dialogs/dialog_fp_lib_table_base.fbp
@@ -1172,6 +1172,94 @@
                                                     <event name="OnUpdateUI"></event>
                                                 </object>
                                             </object>
+                                            <object class="sizeritem" expanded="1">
+                                                <property name="border">5</property>
+                                                <property name="flag">wxALL</property>
+                                                <property name="proportion">0</property>
+                                                <object class="wxButton" expanded="1">
+                                                    <property name="BottomDockable">1</property>
+                                                    <property name="LeftDockable">1</property>
+                                                    <property name="RightDockable">1</property>
+                                                    <property name="TopDockable">1</property>
+                                                    <property name="aui_layer"></property>
+                                                    <property name="aui_name"></property>
+                                                    <property name="aui_position"></property>
+                                                    <property name="aui_row"></property>
+                                                    <property name="best_size"></property>
+                                                    <property name="bg"></property>
+                                                    <property name="caption"></property>
+                                                    <property name="caption_visible">1</property>
+                                                    <property name="center_pane">0</property>
+                                                    <property name="close_button">1</property>
+                                                    <property name="context_help"></property>
+                                                    <property name="context_menu">1</property>
+                                                    <property name="default">0</property>
+                                                    <property name="default_pane">0</property>
+                                                    <property name="dock">Dock</property>
+                                                    <property name="dock_fixed">0</property>
+                                                    <property name="docking">Left</property>
+                                                    <property name="enabled">1</property>
+                                                    <property name="fg"></property>
+                                                    <property name="floatable">1</property>
+                                                    <property name="font"></property>
+                                                    <property name="gripper">0</property>
+                                                    <property name="hidden">0</property>
+                                                    <property name="id">wxID_ANY</property>
+                                                    <property name="label">Options Editor</property>
+                                                    <property name="max_size"></property>
+                                                    <property name="maximize_button">0</property>
+                                                    <property name="maximum_size"></property>
+                                                    <property name="min_size"></property>
+                                                    <property name="minimize_button">0</property>
+                                                    <property name="minimum_size"></property>
+                                                    <property name="moveable">1</property>
+                                                    <property name="name">m_edit_options</property>
+                                                    <property name="pane_border">1</property>
+                                                    <property name="pane_position"></property>
+                                                    <property name="pane_size"></property>
+                                                    <property name="permission">protected</property>
+                                                    <property name="pin_button">1</property>
+                                                    <property name="pos"></property>
+                                                    <property name="resize">Resizable</property>
+                                                    <property name="show">1</property>
+                                                    <property name="size"></property>
+                                                    <property name="style"></property>
+                                                    <property name="subclass"></property>
+                                                    <property name="toolbar_pane">0</property>
+                                                    <property name="tooltip">Zoom into the options table for current row</property>
+                                                    <property name="validator_data_type"></property>
+                                                    <property name="validator_style">wxFILTER_NONE</property>
+                                                    <property name="validator_type">wxDefaultValidator</property>
+                                                    <property name="validator_variable"></property>
+                                                    <property name="window_extra_style"></property>
+                                                    <property name="window_name"></property>
+                                                    <property name="window_style"></property>
+                                                    <event name="OnButtonClick"></event>
+                                                    <event name="OnChar"></event>
+                                                    <event name="OnEnterWindow"></event>
+                                                    <event name="OnEraseBackground"></event>
+                                                    <event name="OnKeyDown"></event>
+                                                    <event name="OnKeyUp"></event>
+                                                    <event name="OnKillFocus"></event>
+                                                    <event name="OnLeaveWindow"></event>
+                                                    <event name="OnLeftDClick"></event>
+                                                    <event name="OnLeftDown">optionsEditor</event>
+                                                    <event name="OnLeftUp"></event>
+                                                    <event name="OnMiddleDClick"></event>
+                                                    <event name="OnMiddleDown"></event>
+                                                    <event name="OnMiddleUp"></event>
+                                                    <event name="OnMotion"></event>
+                                                    <event name="OnMouseEvents"></event>
+                                                    <event name="OnMouseWheel"></event>
+                                                    <event name="OnPaint"></event>
+                                                    <event name="OnRightDClick"></event>
+                                                    <event name="OnRightDown"></event>
+                                                    <event name="OnRightUp"></event>
+                                                    <event name="OnSetFocus"></event>
+                                                    <event name="OnSize"></event>
+                                                    <event name="OnUpdateUI"></event>
+                                                </object>
+                                            </object>
                                         </object>
                                     </object>
                                 </object>
diff --git a/pcbnew/dialogs/dialog_fp_lib_table_base.h b/pcbnew/dialogs/dialog_fp_lib_table_base.h
index 5a0e15dcd0..7cef046001 100644
--- a/pcbnew/dialogs/dialog_fp_lib_table_base.h
+++ b/pcbnew/dialogs/dialog_fp_lib_table_base.h
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Oct  8 2012)
+// C++ code generated with wxFormBuilder (version Apr 30 2013)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO "NOT" EDIT THIS FILE!
@@ -53,6 +53,7 @@ class DIALOG_FP_LIB_TABLE_BASE : public DIALOG_SHIM
 		wxButton* m_delete_button;
 		wxButton* m_move_up_button;
 		wxButton* m_move_down_button;
+		wxButton* m_edit_options;
 		wxPanel* m_bottom;
 		wxGrid* m_path_subs_grid;
 		wxStdDialogButtonSizer* m_sdbSizer1;
@@ -69,6 +70,7 @@ class DIALOG_FP_LIB_TABLE_BASE : public DIALOG_SHIM
 		virtual void deleteRowHandler( wxMouseEvent& event ) { event.Skip(); }
 		virtual void moveUpHandler( wxMouseEvent& event ) { event.Skip(); }
 		virtual void moveDownHandler( wxMouseEvent& event ) { event.Skip(); }
+		virtual void optionsEditor( wxMouseEvent& event ) { event.Skip(); }
 		virtual void onCancelButtonClick( wxCommandEvent& event ) { event.Skip(); }
 		virtual void onOKButtonClick( wxCommandEvent& event ) { event.Skip(); }
 		
diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp
index e728f64d73..0da4e45233 100644
--- a/pcbnew/files.cpp
+++ b/pcbnew/files.cpp
@@ -281,10 +281,15 @@ bool PCB_EDIT_FRAME::LoadOnePcbFile( const wxString& aFileName, bool aAppend,
     try
     {
         PROPERTIES  props;
+        char        xbuf[30];
+        char        ybuf[30];
 
         // EAGLE_PLUGIN can use this info to center the BOARD, but it does not yet.
-        props["page_width"]  = wxString::Format( wxT( "%d" ), GetPageSizeIU().x );
-        props["page_height"] = wxString::Format( wxT( "%d" ), GetPageSizeIU().y );
+        sprintf( xbuf, "%d", GetPageSizeIU().x );
+        sprintf( ybuf, "%d", GetPageSizeIU().y );
+
+        props["page_width"]  = xbuf;
+        props["page_height"] = ybuf;
 
 #if USE_INSTRUMENTATION
         // measure the time to load a BOARD.
diff --git a/pcbnew/io_mgr.cpp b/pcbnew/io_mgr.cpp
index a89e6c0da9..0a3d222748 100644
--- a/pcbnew/io_mgr.cpp
+++ b/pcbnew/io_mgr.cpp
@@ -126,11 +126,8 @@ const wxString IO_MGR::ShowType( PCB_FILE_T aType )
     case GEDA_PCB:
         return wxString( wxT( "Geda-PCB" ) );
 
-#if defined(BUILD_GITHUB_PLUGIN)
     case GITHUB:
         return wxString( wxT( "Github" ) );
-#endif
-
     }
 }
 
@@ -156,10 +153,8 @@ IO_MGR::PCB_FILE_T IO_MGR::EnumFromStr( const wxString& aType )
     if( aType == wxT( "Geda-PCB" ) )
         return GEDA_PCB;
 
-#if defined(BUILD_GITHUB_PLUGIN)
     if( aType == wxT( "Github" ) )
         return GITHUB;
-#endif
 
     // wxASSERT( blow up here )
 
diff --git a/scripts/test_plugin.py b/scripts/test_plugin.py
index 6ffb1298fb..3755607013 100755
--- a/scripts/test_plugin.py
+++ b/scripts/test_plugin.py
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 
-# Convert a footprint library from one format to another, e.g. legacy to pretty.
+# Test a basic back to back FootprintLoad() of a single footprint, and FootprintEnumerate()
 
 # 1) Build target _pcbnew after enabling scripting in cmake.
 # $ make _pcbnew