/* Creates the section $DEVICES
 * This is a list of footprints properties
 *  ( Shapes are in section $SHAPE )
 */
static void CreateDevicesSection( FILE* aFile, BOARD* aPcb )
{
    MODULE* module;

    fputs( "$DEVICES\n", aFile );

    for( module = aPcb->m_Modules; module; module = module->Next() )
    {
        fprintf( aFile, "DEVICE \"%s\"\n", TO_UTF8( module->GetReference() ) );
        fprintf( aFile, "PART \"%s\"\n", TO_UTF8( module->GetValue() ) );
        fprintf( aFile, "PACKAGE \"%s\"\n", module->GetFPID().Format().c_str() );

        // The TYPE attribute is almost freeform
        const char* ty = "TH";

        if( module->GetAttributes() & MOD_CMS )
            ty = "SMD";

        if( module->GetAttributes() & MOD_VIRTUAL )
            ty = "VIRTUAL";

        fprintf( aFile, "TYPE %s\n", ty );
    }

    fputs( "$ENDDEVICES\n\n", aFile );
}
/*
 * Creates a footprint position file
 * aSide = 0 -> Back (bottom) side)
 * aSide = 1 -> Front (top) side)
 * aSide = 2 -> both sides
 * if aFullFileName is empty, the file is not created, only the
 * count of footprints to place is returned
 */
int PCB_EDIT_FRAME::DoGenFootprintsPositionFile( const wxString& aFullFileName,
        bool aUnitsMM,
        bool aForceSmdItems, int aSide )
{
    MODULE*     module;
    char        line[1024];

    File_Place_Offset = GetAuxOrigin();

    // Calculating the number of useful modules (CMS attribute, not VIRTUAL)
    int moduleCount = 0;

    for( module = GetBoard()->m_Modules;  module;  module = module->Next() )
    {
        if( aSide < 2 )
        {
            if( module->GetLayer() == B_Cu && aSide == 1)
                continue;
            if( module->GetLayer() == F_Cu && aSide == 0)
                continue;
        }

        if( module->GetAttributes() & MOD_VIRTUAL )
        {
            DBG( printf( "skipping module %s because it's virtual\n",
                         TO_UTF8( module->GetReference() ) );)
            continue;
        }
/*
 * Creates a footprint position file
 * aSide = 0 -> Back (bottom) side)
 * aSide = 1 -> Front (top) side)
 * aSide = 2 -> both sides
 * if aFullFileName is empty, the file is not created, only the
 * count of footprints to place is returned
 */
int PCB_EDIT_FRAME::DoGenFootprintsPositionFile( const wxString& aFullFileName,
                                                 bool aUnitsMM,
                                                 bool aForceSmdItems, int aSide,
                                                 bool aFormatCSV )
{
    MODULE*     footprint;

    // Minimal text lengths:
    int lenRefText = 8;
    int lenValText = 8;
    int lenPkgText = 16;

    File_Place_Offset = GetAuxOrigin();

    // Calculating the number of useful footprints (CMS attribute, not VIRTUAL)
    int footprintCount = 0;

    // Select units:
    double conv_unit = aUnitsMM ? conv_unit_mm : conv_unit_inch;
    const char *unit_text = aUnitsMM ? unit_text_mm : unit_text_inch;

    // Build and sort the list of footprints alphabetically
    std::vector<LIST_MOD> list;
    list.reserve( footprintCount );

    for( footprint = GetBoard()->m_Modules; footprint; footprint = footprint->Next() )
    {
        if( aSide != PCB_BOTH_SIDES )
        {
            if( footprint->GetLayer() == B_Cu && aSide == PCB_FRONT_SIDE)
                continue;
            if( footprint->GetLayer() == F_Cu && aSide == PCB_BACK_SIDE)
                continue;
        }

        if( footprint->GetAttributes() & MOD_VIRTUAL )
        {
            DBG( printf( "skipping footprint %s because it's virtual\n",
                         TO_UTF8( footprint->GetReference() ) );)
            continue;
        }