Commit 1969a511 authored by dickelbeck's avatar dickelbeck
Browse files

more free specctra dsn work

parent b8b0fc6e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -737,7 +737,7 @@ L_read:
                goto exit;
            }
            
            // else it was something like +5V, reset head back
            // else it was something like +5V, fall through below
        }
        
        // a quoted string
+24 −16
Original line number Diff line number Diff line
@@ -212,7 +212,7 @@ void SPECCTRA_DB::readTIME( time_t* time_stamp ) throw( IOError )
    
    const char* ptok = lexer->CurText();

    mytime.tm_mon = 0;      // remains of we don't find a month match.
    mytime.tm_mon = 0;      // remains if we don't find a month match.
    for( int m=0;  months[m];  ++m )
    {
        if( !stricmp( months[m], ptok ) )
@@ -1985,7 +1985,7 @@ void SPECCTRA_DB::doSHAPE( SHAPE* growth ) throw( IOError )
        case T_polygon:
        case T_qarc:
L_done_that:    
            if( growth->rectangle || growth->circle || growth->path || growth->qarc )
            if( growth->Length() )
                unexpected( tok );
            break;
        default:
@@ -2000,24 +2000,32 @@ L_done_that:
        switch( tok )
        {
        case T_rect:
            growth->rectangle = new RECTANGLE( growth );
            doRECTANGLE( growth->rectangle );
            RECTANGLE* rectangle;
            rectangle = new RECTANGLE( growth );
            growth->Append( rectangle );
            doRECTANGLE( rectangle );
            break;
            
        case T_circle:
            growth->circle = new CIRCLE( growth );
            doCIRCLE( growth->circle );
            CIRCLE* circle;
            circle = new CIRCLE( growth );
            growth->Append( circle );
            doCIRCLE( circle );
            break;
        
        case T_path:
        case T_polygon:
            growth->path = new PATH( growth, tok );
            doPATH( growth->path );
            PATH* path;
            path = new PATH( growth, tok );
            growth->Append( path );
            doPATH( path );
            break;
            
        case T_qarc:
            growth->qarc = new QARC( growth );
            doQARC( growth->qarc );
            QARC* qarc;
            qarc = new QARC( growth );
            growth->Append( qarc );
            doQARC( qarc );
            break;

        case T_connect:
@@ -3650,16 +3658,16 @@ int main( int argc, char** argv )
{
//    wxString    filename( wxT("/tmp/fpcroute/Sample_1sided/demo_1sided.dsn") );
//    wxString    filename( wxT("/tmp/testdesigns/test.dsn") );
    wxString    filename( wxT("/tmp/testdesigns/test.ses") );
//    wxString    filename( wxT("/tmp/specctra_big.dsn") );
//    wxString    filename( wxT("/tmp/testdesigns/test.ses") );
    wxString    filename( wxT("/tmp/specctra_big.dsn") );

    SPECCTRA_DB     db;
    bool            failed = false;
    
    try 
    {
//        db.LoadPCB( filename );
        db.LoadSESSION( filename );
        db.LoadPCB( filename );
//        db.LoadSESSION( filename );
    } 
    catch( IOError ioe )
    {
@@ -3672,8 +3680,8 @@ int main( int argc, char** argv )


    // export what we read in, making this test program basically a beautifier
    db.ExportSESSION( wxT("/tmp/export.ses") );
//    db.ExportPCB( wxT("/tmp/export.dsn") ); 
//    db.ExportSESSION( wxT("/tmp/export.ses") );
    db.ExportPCB( wxT("/tmp/export.dsn") ); 
    
}

+101 −68
Original line number Diff line number Diff line
@@ -111,6 +111,11 @@ struct POINT
    
    POINT() { x=0.0; y=0.0; }
    
    POINT( double aX, double aY ) :
        x(aX), y(aY)
    {
    }
    
    bool operator==( const POINT& other ) const
    {
        return x==other.x && y==other.y;
@@ -407,6 +412,17 @@ public:
    {
    }

    void SetLayerId( const char* aLayerId )
    {
        layer_id = aLayerId;
    }
    
    void SetCorners( const POINT& aPoint0, const POINT& aPoint1 )
    {
        point0 = aPoint0;
        point1 = aPoint1;
    }
    
    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    {
        const char*  quote = out->GetQuoteChar( layer_id.c_str() );
@@ -451,9 +467,10 @@ public:
        
        else
        {
            out->Print( 0, "\n" );
            singleLine = false;
            for( STRINGS::const_iterator i = rules.begin();  i!=rules.end(); ++i )
                out->Print( nestLevel, "%s\n", i->c_str() );
                out->Print( nestLevel+1, "%s\n", i->c_str() );
            out->Print( nestLevel, ")" );
        }
        
@@ -671,6 +688,16 @@ public:
                                 quote, layer_id.c_str(), quote,
                                 diameter, vertex.x, vertex.y );
    }
    
    void SetLayerId( const char* aLayerId )
    {
        layer_id = aLayerId;
    }
    
    void SetDiameter( double aDiameter )
    {
        diameter = aDiameter;
    }
};


@@ -870,28 +897,42 @@ public:
    
    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    {
        out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) );
        const int RIGHTMARGIN = 80;
        int perLine = out->Print( nestLevel, "(%s", LEXER::GetTokenText( Type() ) );
        
        for( STRINGS::iterator i=padstacks.begin();  i!=padstacks.end();  ++i )
        {
            if( perLine > RIGHTMARGIN )
            {
                out->Print( 0, "\n" );
                perLine = out->Print( nestLevel+1, "%s", "");
            }

            const char* quote = out->GetQuoteChar( i->c_str() );
            out->Print( nestLevel+1, "%s%s%s\n", quote, i->c_str(), quote );
            perLine += out->Print( 0, " %s%s%s", quote, i->c_str(), quote );
        }
        
        if( spares.size() )
        {
            out->Print( nestLevel+1, "(spare\n" );
            out->Print( 0, "\n" );
            
            perLine = out->Print( nestLevel+1, "(spare" );

            for( STRINGS::iterator i=spares.begin();  i!=spares.end();  ++i )
            {
                if( perLine > RIGHTMARGIN )
                {
                    out->Print( 0, "\n" );
                    perLine = out->Print( nestLevel+2, "%s", "");
                }
                const char* quote = out->GetQuoteChar( i->c_str() );
                out->Print( nestLevel+2, "%s%s%s\n", quote, i->c_str(), quote );
                perLine += out->Print( 0, " %s%s%s", quote, i->c_str(), quote );
            }
            
            out->Print( nestLevel+1, ")\n" );
            out->Print( 0, ")" );
        }
        
        out->Print( nestLevel, ")\n" );
        out->Print( 0, ")\n" );
    }
};

@@ -1600,55 +1641,34 @@ public:
};


class SHAPE : public ELEM
class SHAPE : public ELEM_HOLDER
{
    friend class SPECCTRA_DB;

    DSN_T           connect;
    
    //----- only one of these is used, like a union -----
    /*----- only one of these is used, like a union -----
    single item, but now in the kids list
    
    PATH*           path;           ///< used for both path and polygon
    RECTANGLE*      rectangle;
    CIRCLE*         circle;
    QARC*           qarc;
    //---------------------------------------------------
    //--------------------------------------------------- */
    
    WINDOWS         windows;
    
    
public:
    SHAPE( ELEM* aParent, DSN_T aType = T_shape ) :
        ELEM( aType, aParent )
        ELEM_HOLDER( aType, aParent )
    {
        connect = T_on;
        
        path = 0;
        rectangle = 0;
        circle = 0;
        qarc = 0;
    }
    
    ~SHAPE()
    {
        delete path;
        delete rectangle;
        delete circle;
        delete qarc;
    }
    
    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    {
        if( path )
            path->Format( out, nestLevel );
        
        else if( rectangle )
            rectangle->Format( out, nestLevel );
        
        else if( circle )
            circle->Format( out, nestLevel );
        
        else if( qarc )
            qarc->Format( out, nestLevel );
        ELEM_HOLDER::FormatContents( out, nestLevel );
        
        if( connect == T_off )
            out->Print( nestLevel, "(connect %s)\n", LEXER::GetTokenText( connect ) );
@@ -1817,6 +1837,11 @@ public:
        delete rules;
    }

    void SetPadstackId( const char* aPadstackId )
    {
        padstack_id = aPadstackId;
    }
    
    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    {
        const char* quote = out->GetQuoteChar( padstack_id.c_str() );
@@ -1865,6 +1890,7 @@ public:
        return ELEM::GetUnits();
    }
};
typedef boost::ptr_vector<PADSTACK> PADSTACKS;


/**
@@ -1882,7 +1908,6 @@ class LIBRARY : public ELEM
    typedef boost::ptr_vector<IMAGE>    IMAGES;
    IMAGES          images;

    typedef boost::ptr_vector<PADSTACK> PADSTACKS;
    PADSTACKS       padstacks;

public:
@@ -1916,6 +1941,11 @@ public:
        
        return ELEM::GetUnits();
    }
    
    void AddPadstack( PADSTACK* aPadstack )
    {
        padstacks.push_back( aPadstack );
    }
};


@@ -2215,35 +2245,32 @@ public:
    
    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    {
        const int RIGHTMARGIN = 80;
        
        const char* quote = out->GetQuoteChar( class_id.c_str() );
        out->Print( nestLevel, "(%s %s%s%s", LEXER::GetTokenText( Type() ),
                                 quote, class_id.c_str(), quote );
        
        const int NETGAP = 2;
        const int RIGHTMARGIN = 92;
        int perLine = out->Print( nestLevel, "(%s %s%s%s", 
                              LEXER::GetTokenText( Type() ),
                              quote, class_id.c_str(), quote );

        int perRow=RIGHTMARGIN;
        for( STRINGS::iterator i=net_ids.begin();  i!=net_ids.end();  ++i )
        {
            quote = out->GetQuoteChar( i->c_str() );
            int slength = strlen( i->c_str() );
            if( *quote!='\0' )
                slength += 2;

            if( perRow + slength + NETGAP > RIGHTMARGIN )
            if( perLine > RIGHTMARGIN )
            {
                out->Print( 0, "\n" );
                perRow = 0;
                perRow += out->Print( nestLevel+1, "%s%s%s", 
                                     quote, i->c_str(), quote );
            }
            else
            {
                perRow += out->Print( 0, "%*c%s%s%s", NETGAP, ' ',
                                     quote, i->c_str(), quote );
                perLine = out->Print( nestLevel+1, "%s", "" );
            }
            
            quote = out->GetQuoteChar( i->c_str() );
            perLine += out->Print( 0, " %s%s%s", quote, i->c_str(), quote );
        }
        
        bool newLine = false;
        if( circuit.size() || layer_rules.size() || topology )
        {
            out->Print( 0, "\n" );
            newLine = true;
        }

        for( STRINGS::iterator i=circuit.begin();  i!=circuit.end();  ++i )
            out->Print( nestLevel+1, "%s\n", i->c_str() );
@@ -2254,7 +2281,7 @@ public:
        if( topology )
            topology->Format( out, nestLevel+1 );
        
        out->Print( nestLevel, ")\n" );
        out->Print( newLine ? nestLevel : 0, ")\n" );
    }
};
    
@@ -2444,6 +2471,9 @@ public:
            perLine += out->Print( 0, "%.6g %.6g", i->x, i->y ); 
        }
        
        if( net_id.size() || via_number!=-1 || type!=T_NONE || attr!=T_NONE || supply)
            out->Print( 0, " " );
        
        if( net_id.size() )
        {
            if( perLine > RIGHTMARGIN )
@@ -3183,13 +3213,6 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
    void doSUPPLY_PIN( SUPPLY_PIN* growth ) throw( IOError );    

    
    /**
     * Function exportEdges
     * exports the EDGES_N layer of the board.
     */
    void exportEdges( BOARD* aBoard ) throw( IOError );

    
public:

    SPECCTRA_DB()
@@ -3288,7 +3311,17 @@ public:
    
    /**
     * Function FromBOARD
     * adds the entire BOARD to the PCB but does not write it out.
     * adds the entire BOARD to the PCB but does not write it out.  Note that
     * the BOARD given to this function must have all the MODULEs on the component
     * side of the BOARD.
     *
     * See void WinEDA_PcbFrame::ExportToSPECCTRA( wxCommandEvent& event )
     * for how this can be done before calling this function.  
     * @todo
     * I would have liked to put the flipping logic into the ExportToSPECCTRA()
     * function directly, but for some strange reason, 
     * void Change_Side_Module( MODULE* Module, wxDC* DC ) is a member of 
     * of class WinEDA_BasePcbFrame rather than class BOARD.
     *
     * @param aBoard The BOARD to convert to a PCB.
     * @throw IOError, if the BOARD cannot be converted, and the text of the
+289 −19
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@

#include "specctra.h"
#include "collectors.h"
#include "wxPcbStruct.h"        // Change_Side_Module()

using namespace DSN;

@@ -61,27 +62,59 @@ void WinEDA_PcbFrame::ExportToSPECCTRA( wxCommandEvent& event )

    
    SPECCTRA_DB     db;
    bool            ok = true;
    wxString        errorText;
    
    db.SetPCB( SPECCTRA_DB::MakePCB() );


    //  DSN Images (=Kicad MODULES and pads) must be presented from the
    //  top view.  So we temporarily flip any modules which are on the back
    //  side of the board to the front, and record this in the MODULE's flag field.
    for( MODULE* module = m_Pcb->m_Modules;  module;  module = module->Next() )
    {
        module->flag = 0;
        if( module->GetLayer() == COPPER_LAYER_N )
        {
            Change_Side_Module( module, NULL );
            module->flag = 1;
        }
    }
    
    try 
    {    
        db.FromBOARD( m_Pcb );
        db.ExportPCB(  fullFileName, true );
    
        // if an exception is thrown by FromBOARD or Export(), then 
        // if an exception is thrown by FromBOARD or ExportPCB(), then 
        // ~SPECCTRA_DB() will close the file.
    } 
    catch ( IOError ioe )
    {
        DisplayError( this, ioe.errorText );
        return;
    }
        ok = false;
        
    // @todo display a message saying the export is complete.
        // display no messages until we flip back the modules below.
        errorText = ioe.errorText;
    }

    //  DSN Images (=Kicad MODULES and pads) must be presented from the
    //  top view.  Restore those that were flipped.
    for( MODULE* module = m_Pcb->m_Modules;  module;  module = module->Next() )
    {
        if( module->flag )
        {
            Change_Side_Module( module, NULL );
            module->flag = 0;
        }
    }
    
    if( ok )
    {
        // @todo display a message saying the export is complete.
    }
    else
        DisplayError( this, errorText );
}


namespace DSN {
@@ -103,6 +136,22 @@ static inline void swap( POINT_PAIR& pair )
}


static inline double scale( int kicadDist )
{
    return kicadDist/10.0;
}

static inline double mapX( int x )
{
    return scale(x);
}

static inline double mapY( int y )
{
    return -scale(y);      // make y negative, since it is increasing going down.
}


/**
 * Function mapPt
 * converts a Kicad point into a DSN file point.  Kicad's BOARD coordinates
@@ -112,8 +161,8 @@ static inline void swap( POINT_PAIR& pair )
static POINT mapPt( const wxPoint& pt )
{
    POINT ret;
    ret.x = pt.x / 10.0;
    ret.y = -pt.y /10.0;      // make y negative, since it is increasing going down.
    ret.x = mapX( pt.x );
    ret.y = mapY( pt.y );
    return ret;
}

@@ -172,8 +221,199 @@ static bool isRectangle( POINT_PAIRS& aList )
}


void SPECCTRA_DB::exportEdges( BOARD* aBoard ) throw( IOError )
/**************************************************************************/
static int Pad_list_Sort_by_Shapes( const void* refptr, const void* objptr )
/**************************************************************************/
{
    const D_PAD* padref = *(D_PAD**)refptr;
    const D_PAD* padcmp = *(D_PAD**)objptr;

    return D_PAD::Compare( padref, padcmp );     
}


/**
 * Function makePADSTACKs
 * makes all the PADSTACKs, and marks each D_PAD with the index into the 
 * LIBRARY::padstacks list that it matches.
 */
static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, 
                          LIBRARY* aLibrary, PADSTACKS& aPadstacks )
{
    if( aPads.GetCount() )
    {
        qsort( (void*) aPads.BasePtr(), aPads.GetCount(), sizeof(D_PAD*), Pad_list_Sort_by_Shapes );
    }

    D_PAD*  old_pad = NULL;
    int     padstackNdx = 0;
    
    for( int i=0;  i<aPads.GetCount();  ++i )
    {
        D_PAD*  pad = (D_PAD*) aPads[i];

        pad->m_logical_connexion = padstackNdx;

        if( old_pad  && 0==D_PAD::Compare( old_pad, pad ) )
        {
            continue;
        }

        old_pad = pad;

        // this is the index into the library->padstacks, be careful.
        pad->m_logical_connexion = padstackNdx++;

        PADSTACK*   padstack = new PADSTACK( aLibrary );
        SHAPE*      shape = new SHAPE( padstack );
        padstack->Append( shape );
        
        switch( pad->m_PadShape )
        {
        default:
        case PAD_CIRCLE:
            {
                CIRCLE* circle;
                double  diameter = scale(pad->m_Size.x);
                int coppers = 0;

                if( pad->IsOnLayer( COPPER_LAYER_N ) )
                {
                    circle = new CIRCLE( shape );
                    circle->SetLayerId( CONV_TO_UTF8(aBoard->GetLayerName( COPPER_LAYER_N )) );
                    circle->SetDiameter( diameter );
                    shape->Append( circle );
                    ++coppers;
                }
                
                if( pad->IsOnLayer( LAYER_CMP_N ) )
                {
                    circle = new CIRCLE( shape );
                    circle->SetLayerId( CONV_TO_UTF8(aBoard->GetLayerName( LAYER_CMP_N )) );
                    circle->SetDiameter( diameter );
                    shape->Append( circle );
                    ++coppers;
                }

                char    name[50];
                
                snprintf( name, sizeof(name),  "Round%dPad_%.6g_mil", coppers, scale(pad->m_Size.x) );
                
                name[ sizeof(name)-1 ] = 0;

                // @todo verify that all pad names are unique, there is a chance that 
                // D_PAD::Compare() could say two pads are different, yet the get the same
                // name here. If so, blend in the padNdx into the name.
                
                padstack->SetPadstackId( name );
                
                aLibrary->AddPadstack( padstack );
            }
            break;

        case PAD_RECT:
            {
                double dx = scale( pad->m_Size.x ) / 2.0;
                double dy = scale( pad->m_Size.y ) / 2.0;

                RECTANGLE* rect;
                int coppers = 0;

                if( pad->IsOnLayer( COPPER_LAYER_N ) )
                {
                    rect = new RECTANGLE( shape );
                    rect->SetLayerId( CONV_TO_UTF8(aBoard->GetLayerName( COPPER_LAYER_N )) );
                    rect->SetCorners( POINT(-dx,-dy), POINT(dx,dy) );
                    shape->Append( rect );
                    ++coppers;
                }
                
                if( pad->IsOnLayer( LAYER_CMP_N ) )
                {
                    rect = new RECTANGLE( shape );
                    rect->SetLayerId( CONV_TO_UTF8(aBoard->GetLayerName( LAYER_CMP_N )) );
                    rect->SetCorners( POINT(-dx,-dy), POINT(dx,dy) );
                    shape->Append( rect );
                    ++coppers;
                }

                char    name[50];
                
                snprintf( name, sizeof(name),  "Rect%dPad_%.6gx%.6g_mil", 
                         coppers, scale(pad->m_Size.x), scale(pad->m_Size.y)  );
                
                name[ sizeof(name)-1 ] = 0;

                // @todo verify that all pad names are unique, there is a chance that 
                // D_PAD::Compare() could say two pads are different, yet the get the same
                // name here. If so, blend in the padNdx into the name.
                
                padstack->SetPadstackId( name );
                
                aLibrary->AddPadstack( padstack );
            }
            break;
#if 0            
            pad_type = "RECTANGULAR";
            fprintf( file, " %s %d\n", pad_type, pad->m_Drill.x );
            fprintf( file, "RECTANGLE %d %d %d %d\n",
                     -dx + pad->m_Offset.x, -dy - pad->m_Offset.y,
                     dx + pad->m_Offset.x, -pad->m_Offset.y + dy );
            break;
    
        case PAD_OVAL:     /* description du contour par 2 linges et 2 arcs */
        {
            pad_type = "FINGER";
            fprintf( file, " %s %d\n", pad_type, pad->m_Drill.x );
            int dr = dx - dy;
            if( dr >= 0 )       // ovale horizontal
            {
                int rayon = dy;
                fprintf( file, "LINE %d %d %d %d\n",
                         -dr + pad->m_Offset.x, -pad->m_Offset.y - rayon,
                         dr + pad->m_Offset.x, -pad->m_Offset.y - rayon );
                fprintf( file, "ARC %d %d %d %d %d %d\n",
                         dr + pad->m_Offset.x, -pad->m_Offset.y - rayon,
                         dr + pad->m_Offset.x, -pad->m_Offset.y + rayon,
                         dr + pad->m_Offset.x, -pad->m_Offset.y );
    
                fprintf( file, "LINE %d %d %d %d\n",
                         dr + pad->m_Offset.x, -pad->m_Offset.y + rayon,
                         -dr + pad->m_Offset.x, -pad->m_Offset.y + rayon );
                fprintf( file, "ARC %d %d %d %d %d %d\n",
                         -dr + pad->m_Offset.x, -pad->m_Offset.y + rayon,
                         -dr + pad->m_Offset.x, -pad->m_Offset.y - rayon,
                         -dr + pad->m_Offset.x, -pad->m_Offset.y );
            }
            else        // ovale vertical
            {
                dr = -dr;
                int rayon = dx;
                fprintf( file, "LINE %d %d %d %d\n",
                         -rayon + pad->m_Offset.x, -pad->m_Offset.y - dr,
                         -rayon + pad->m_Offset.x, -pad->m_Offset.y + dr );
                fprintf( file, "ARC %d %d %d %d %d %d\n",
                         -rayon + pad->m_Offset.x, -pad->m_Offset.y + dr,
                         rayon + pad->m_Offset.x, -pad->m_Offset.y + dr,
                         pad->m_Offset.x, -pad->m_Offset.y + dr );
    
                fprintf( file, "LINE %d %d %d %d\n",
                         rayon + pad->m_Offset.x, -pad->m_Offset.y + dr,
                         rayon + pad->m_Offset.x, -pad->m_Offset.y - dr );
                fprintf( file, "ARC %d %d %d %d %d %d\n",
                         rayon + pad->m_Offset.x, -pad->m_Offset.y - dr,
                         -rayon + pad->m_Offset.x, -pad->m_Offset.y - dr,
                         pad->m_Offset.x, -pad->m_Offset.y - dr );
            }
            break;
        }
    
        case PAD_TRAPEZOID:
            pad_type = "POLYGON";
            break;
#endif
        }
    }
}


@@ -304,6 +544,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
        }
    }

    
    //-----<zone containers become planes>--------------------------------------------
    {
        static const KICAD_T  scanZONEs[] = { TYPEZONE_CONTAINER, EOT };
@@ -334,19 +575,48 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
        }
    }

    // keepouts could go here, there are none in Kicad at this time.
    // although COPPER_PLANEs probably will need them for the thru holes, etc.
    // but in that case they are WINDOWs within the COPPER_PLANEs.

    
    //-----<build the padstack list here, no output>------------------------
    {
        // get all the DRAWSEGMENTS into 'items', then look for layer == EDGE_N,
        // and those segments comprize the board's perimeter.
        static const KICAD_T  scanPADnVIAs[] = { TYPEPAD, TYPEVIA, EOT };
        items.Collect( aBoard, scanPADnVIAs );
        static const KICAD_T scanPADs[] = { TYPEPAD, EOT };

        for( int i=0;  i<items.GetCount();  ++i )
        TYPE_COLLECTOR  pads;

        // get all the D_PADs into pads.        
        pads.Collect( aBoard, scanPADs );

        makePADSTACKs( aBoard, pads, pcb->library, pcb->library->padstacks );

        for( int p=0;  p<pads.GetCount();  ++p )
            pads[p]->Show( 0, std::cout );
        
/*        
        static const KICAD_T scanMODULEs[] = { TYPEMODULE, EOT };
        
        items.Collect( aBoard, scanMODULEs );

        for( int m=0;  m<items.GetCount();  ++m )
        {
//            items[i]->Show( 0, std::cout );
            MODULE* module = (MODULE*) items[m];
            

            // collate all the pads, and make a component.
            for( int p=0;  p<pads.GetCount();  ++p )
            {
                D_PAD* pad = (D_PAD*) pads[p];
                
                D(pad->Show( 0, std::cout );)
                
                // lookup and maybe add this pad to the padstack.
                wxString padName = lookupPad( pcb->library->padstacks, pad ); 
            }
        }
    
*/        
    }
    
    //-----<via_descriptor>-------------------------------------------------
    {