kicad/pcbnew/ioascii.cpp

1084 lines
34 KiB
C++
Raw Normal View History

2007-12-11 20:26:40 +00:00
/********************************************************************/
/* Routines de lecture et sauvegarde des structures en format ASCii */
/* Fichier common a PCBNEW et CVPCB */
/********************************************************************/
/* ioascii.cpp */
#include "fctsys.h"
#include "common.h"
#include "confirm.h"
#include "kicad_string.h"
#include "pcbnew.h"
2009-07-30 11:04:07 +00:00
#include "wxPcbStruct.h"
2009-10-28 11:48:47 +00:00
#include "class_board_design_settings.h"
#ifdef PCBNEW
#include "autorout.h"
2008-10-20 08:25:06 +00:00
#include "zones.h"
#endif
#ifdef CVPCB
#include "cvpcb.h"
#endif
#include "pcbnew_id.h"
/* Format des structures de sauvegarde type ASCII :
Structure PAD:
$PAD
Sh "name" forme dimv dimH dV dH orient :forme generale dV, dH = delta dimensions
Dr diam, dV dH :drill : diametre offsets de percage
At type S/N layers : type standard,cms,conn,hole,meca.,
Stack/Normal,
Hexadecimal 32 bits: occupation des couches
Nm net_code netname
Po posrefX posrefy : position refX,Y (= position orient 0 / ancre)
$EndPAD
****** Structure module ***********
$MODULE namelib
Po ax ay orient layer masquelayer m_TimeCode
ax ay = coord ancre (position module)
orient = orient en 0.1 degre
layer = numero de couche
masquelayer = couche pour serigraphie
m_TimeCode a usage interne (groupements)
Li <namelib>
Cd <text> Description du composant (Composant Doc)
Kw <text> Liste des mots cle
Sc schematimestamp de reference schematique
Op rot90 rot180 Options de placement auto (cout rot 90, 180 )
rot90 est sur 2x4 bits:
lsb = cout rot 90, msb = cout rot -90;
Tn px py dimv dimh orient epaisseur miroir visible "texte"
n = type (0 = ref, 1 = val, > 1 =qcq
Textes POS x,y / ancre et orient module 0
dimv dimh orient
epaisseur miroir (Normal/miroir)
visible V/I
DS ox oy fx fy w
edge: segment coord ox,oy a fx,fy, relatives
a l'ancre et orient 0
epaisseur w
DC ox oy fx fy w descr cercle (centre, 1 point, epaisseur)
$PAD
$EndPAD section pads s'il y en a
$EndMODULE
*/
/* Local Variables */
int NbDraw, NbTrack, NbZone, NbMod, NbNets;
/**********************************************************************/
int WinEDA_BasePcbFrame::ReadListeSegmentDescr( FILE* File,
TRACK* insertBeforeMe, int StructType, int* LineNum, int NumSegm )
/**********************************************************************/
/** Read a list of segments (Tracks, zones)
* @return items count or - count if no end block ($End...) found.
*/
{
int shape, width, drill, layer, type, flags, net_code;
int ii = 0;
2007-08-30 22:20:52 +00:00
char line1[256];
char line2[256];
2008-03-01 13:15:41 +00:00
TRACK* newTrack;
2007-08-30 22:20:52 +00:00
while( GetLine( File, line1, LineNum ) )
{
2007-08-30 22:20:52 +00:00
int makeType;
unsigned long timeStamp;
2008-03-01 13:15:41 +00:00
2007-08-30 22:20:52 +00:00
if( line1[0] == '$' )
{
return ii; /* end of segmentlist: OK */
}
2007-08-30 22:20:52 +00:00
// Read the 2nd line to determine the exact type, one of:
// TYPE_TRACK, TYPE_VIA, or TYPE_ZONE. The type field in 2nd line
// differentiates between TYPE_TRACK and TYPE_VIA. With virtual
// functions in use, it is critical to instantiate the TYPE_VIA exactly.
2007-08-30 22:20:52 +00:00
if( GetLine( File, line2, LineNum ) == NULL )
break;
2008-03-01 13:15:41 +00:00
2007-08-30 22:20:52 +00:00
if( line2[0] == '$' )
break;
// parse the 2nd line first to determine the type of object
sscanf( line2 + 2, " %d %d %d %lX %X", &layer, &type, &net_code,
&timeStamp, &flags );
if( StructType==TYPE_TRACK && type==1 )
makeType = TYPE_VIA;
2007-08-30 22:20:52 +00:00
else
makeType = StructType;
2008-03-01 13:15:41 +00:00
2007-08-30 22:20:52 +00:00
switch( makeType )
{
default:
case TYPE_TRACK:
newTrack = new TRACK( GetBoard() );
GetBoard()->m_Track.Insert( newTrack, insertBeforeMe );
break;
case TYPE_VIA:
newTrack = new SEGVIA( GetBoard() );
GetBoard()->m_Track.Insert( newTrack, insertBeforeMe );
break;
2009-08-08 06:07:08 +00:00
case TYPE_ZONE: // this is now deprecated, but exits in old boards
newTrack = new SEGZONE( GetBoard() );
GetBoard()->m_Zone.Insert( (SEGZONE*)newTrack, (SEGZONE*)insertBeforeMe );
break;
}
newTrack->m_TimeStamp = timeStamp;
2007-08-30 22:20:52 +00:00
int arg_count = sscanf( line1 + 2, " %d %d %d %d %d %d %d", &shape,
&newTrack->m_Start.x, &newTrack->m_Start.y,
&newTrack->m_End.x, &newTrack->m_End.y, &width,
&drill );
newTrack->m_Width = width;
newTrack->m_Shape = shape;
2007-10-15 07:50:59 +00:00
if( arg_count < 7 || drill <= 0 )
newTrack->SetDrillDefault();
2008-03-01 13:15:41 +00:00
else
newTrack->SetDrillValue(drill);
newTrack->SetLayer( layer );
2009-05-21 12:45:21 +00:00
if ( makeType == TYPE_VIA )
{ // Ensure layers are OK when possible:
if( newTrack->Shape() == VIA_THROUGH )
((SEGVIA*)newTrack)->SetLayerPair( LAYER_CMP_N, COPPER_LAYER_N );
}
newTrack->SetNet( net_code );
newTrack->SetState( flags, ON );
}
DisplayError( this, _( "Error: Unexpected end of file !" ) );
return -ii;
}
/**********************************************************************************/
int WinEDA_BasePcbFrame::ReadGeneralDescrPcb( FILE* File, int* LineNum )
/**********************************************************************************/
{
char Line[1024], * data;
while( GetLine( File, Line, LineNum ) != NULL )
{
data = strtok( Line, " =\n\r" );
if( strnicmp( data, "$EndGENERAL", 10 ) == 0 )
break;
2009-10-10 01:25:53 +00:00
if( stricmp( data, "EnabledLayers" ) == 0 )
{
int EnabledLayers = 0;
data = strtok( NULL, " =\n\r" );
sscanf( data, "%X", &EnabledLayers );
// Setup layer visibility
GetBoard()->SetEnabledLayers( EnabledLayers );
2009-10-10 01:25:53 +00:00
continue;
}
if( stricmp( data, "VisibleLayers" ) == 0 )
{
int VisibleLayers = 0;
data = strtok( NULL, " =\n\r" );
sscanf( data, "%X", &VisibleLayers );
// Setup layer visibility
GetBoard()->SetVisibleLayers( VisibleLayers );
2009-10-10 01:25:53 +00:00
continue;
}
if( stricmp( data, "VisibleElements" ) == 0 )
{
int VisibleElements = 0;
data = strtok( NULL, " =\n\r" );
sscanf( data, "%X", &VisibleElements );
// Setup elements visibility
GetBoard()->SetVisibleElements( VisibleElements );
2009-10-10 01:25:53 +00:00
continue;
}
if( strncmp( data, "Ly", 2 ) == 0 ) // Old format for Layer count
{
int Masque_Layer = 1, ii;
data = strtok( NULL, " =\n\r" );
sscanf( data, "%X", &Masque_Layer );
// Setup layer count
2009-10-28 11:48:47 +00:00
int layer_count = 0;
for( ii = 0; ii < NB_COPPER_LAYERS; ii++ )
{
if( Masque_Layer & 1 )
2009-10-28 11:48:47 +00:00
layer_count++;
Masque_Layer >>= 1;
}
2009-10-28 11:48:47 +00:00
GetBoard()->m_BoardSettings->SetCopperLayerCount( layer_count );
continue;
}
if( stricmp( data, "LayerThickness" ) == 0 )
{
data = strtok( NULL, " =\n\r" );
GetBoard()->m_BoardSettings->m_LayerThickness = atoi( data );;
continue;
}
if( strnicmp( data, "Links", 5 ) == 0 )
{
// Info only, do nothing
continue;
}
if( strnicmp( data, "NoConn", 6 ) == 0 )
{
data = strtok( NULL, " =\n\r" );
GetBoard()->m_NbNoconnect = atoi( data );
continue;
}
if( strnicmp( data, "Di", 2 ) == 0 )
{
wxSize pcbsize, screensize;
data = strtok( NULL, " =\n\r" );
GetBoard()->m_BoundaryBox.SetX( atoi( data ) );
data = strtok( NULL, " =\n\r" );
GetBoard()->m_BoundaryBox.SetY( atoi( data ) );
data = strtok( NULL, " =\n\r" );
GetBoard()->m_BoundaryBox.SetWidth( atoi( data ) - GetBoard()->m_BoundaryBox.GetX() );
data = strtok( NULL, " =\n\r" );
GetBoard()->m_BoundaryBox.SetHeight( atoi( data ) - GetBoard()->m_BoundaryBox.GetY() );
continue;
}
/* Lecture du nombre de segments type DRAW , TRACT, ZONE */
if( stricmp( data, "Ndraw" ) == 0 )
{
data = strtok( NULL, " =\n\r" );
NbDraw = atoi( data );;
continue;
}
if( stricmp( data, "Ntrack" ) == 0 )
{
data = strtok( NULL, " =\n\r" );
NbTrack = atoi( data );
continue;
}
if( stricmp( data, "Nzone" ) == 0 )
{
data = strtok( NULL, " =\n\r" );
NbZone = atoi( data );
continue;
}
if( stricmp( data, "Nmodule" ) == 0 )
{
data = strtok( NULL, " =\n\r" );
NbMod = atoi( data );
continue;
}
if( stricmp( data, "Nnets" ) == 0 )
{
data = strtok( NULL, " =\n\r" );
NbNets = atoi( data );
continue;
}
}
return 1;
}
/*************************************************************/
int WinEDA_BasePcbFrame::ReadSetup( FILE* File, int* LineNum )
/*************************************************************/
{
2009-09-10 15:22:26 +00:00
char Line[1024];
char* data;
NETCLASS * netclass_default = GetBoard()->m_NetClasses.GetDefault();
while( GetLine( File, Line, LineNum ) != NULL )
{
strtok( Line, " =\n\r" );
data = strtok( NULL, " =\n\r" );
if( stricmp( Line, "$EndSETUP" ) == 0 )
{
2009-09-10 15:22:26 +00:00
// Until such time as the *.brd file does not have the global parameters:
// "TrackWidth", "TrackMinWidth", "ViaSize", "ViaDrill", "ViaMinSize", and "TrackClearence",
// put those same global values into the default NETCLASS until later board load
// code should override them. *.brd files which have been saved with knowledge of
// NETCLASSes will override these defaults, old boards will not.
// @todo: I expect that at some point we can remove said global
// parameters from the *.brd file since the ones in the default
// netclass serve the same purpose. If needed at all, the global defaults should go into
// a preferences file instead so they are there to start new board projects.
GetBoard()->m_NetClasses.GetDefault()->SetParams();
return 0;
}
if( stricmp( Line, "AuxiliaryAxisOrg" ) == 0 )
{
int gx = 0, gy = 0;
gx = atoi( data );
data = strtok( NULL, " =\n\r" );
if( data )
gy = atoi( data );
2008-03-01 13:15:41 +00:00
m_Auxiliary_Axis_Position.x = gx;
2007-10-13 06:18:44 +00:00
m_Auxiliary_Axis_Position.y = gy;
continue;
}
#ifdef PCBNEW
if( stricmp( Line, "Layers" ) == 0 )
{
int tmp;
sscanf( data, "%d", &tmp );
2009-10-28 11:48:47 +00:00
GetBoard()->m_BoardSettings->SetCopperLayerCount( tmp );
continue;
}
2008-03-01 13:15:41 +00:00
const int LAYERKEYZ = sizeof("Layer[")-1;
if( strncmp( Line, "Layer[", LAYERKEYZ ) == 0 )
{
2008-03-04 04:22:27 +00:00
// parse:
2008-03-04 14:27:48 +00:00
// Layer[n] <a_Layer_name_with_no_spaces> <LAYER_T>
2008-03-04 04:22:27 +00:00
char* cp = Line + LAYERKEYZ;
2008-03-01 13:15:41 +00:00
int layer = atoi(cp);
2008-03-04 04:22:27 +00:00
if( data )
{
wxString layerName = CONV_FROM_UTF8( data );
GetBoard()->SetLayerName( layer, layerName );
2008-03-04 04:22:27 +00:00
data = strtok( NULL, " " );
if( data )
{
LAYER_T type = LAYER::ParseType( data );
GetBoard()->SetLayerType( layer, type );
2008-03-04 04:22:27 +00:00
}
}
2008-03-01 13:15:41 +00:00
continue;
}
if( stricmp( Line, "TrackWidth" ) == 0 ) // no more used
{
continue;
}
if( stricmp( Line, "TrackWidthList" ) == 0 )
{
int tmp = atoi( data );
GetBoard()->m_TrackWidthList.push_back( tmp );
continue;
}
if( stricmp( Line, "TrackClearence" ) == 0 )
{
netclass_default->SetClearance( atoi( data ) );
continue;
}
if( stricmp( Line, "TrackMinWidth" ) == 0 )
{
g_DesignSettings.m_TrackMinWidth = atoi( data );
continue;
}
2009-09-10 15:22:26 +00:00
if( stricmp( Line, "ZoneClearence" ) == 0 )
{
2008-10-23 10:26:06 +00:00
g_Zone_Default_Setting.m_ZoneClearance = atoi( data );
continue;
}
if( stricmp( Line, "DrawSegmWidth" ) == 0 )
{
g_DesignSettings.m_DrawSegmentWidth = atoi( data );
continue;
}
if( stricmp( Line, "EdgeSegmWidth" ) == 0 )
{
g_DesignSettings.m_EdgeSegmentWidth = atoi( data );
continue;
}
if( stricmp( Line, "ViaSize" ) == 0 ) // no more used
{
continue;
}
if( stricmp( Line, "ViaMinSize" ) == 0 )
{
g_DesignSettings.m_ViasMinSize = atoi( data );
continue;
}
if( stricmp( Line, "MicroViaSize" ) == 0 ) // Not used
{
continue;
}
if( stricmp( Line, "MicroViaMinSize" ) == 0 )
{
g_DesignSettings.m_MicroViasMinSize = atoi( data );
continue;
}
if( stricmp( Line, "ViaSizeList" ) == 0 )
{
int tmp = atoi( data );
VIA_DIMENSION via_dim;
via_dim.m_Diameter = tmp;
data = strtok( NULL, " \n\r" );
if( data )
{
tmp = atoi( data );
via_dim.m_Drill = tmp > 0 ? tmp : 0;
}
GetBoard()->m_ViasDimensionsList.push_back( via_dim );
continue;
}
if( stricmp( Line, "ViaDrill" ) == 0 )
{
int diameter = atoi( data );
netclass_default->SetViaDrill( diameter );
continue;
}
if( stricmp( Line, "ViaMinDrill" ) == 0 )
{
g_DesignSettings.m_ViasMinDrill = atoi( data );
continue;
}
if( stricmp( Line, "MicroViaDrill" ) == 0 )
{
int diameter = atoi( data );
netclass_default->SetuViaDrill( diameter );
continue;
}
if( stricmp( Line, "MicroViaMinDrill" ) == 0 )
{
int diameter = atoi( data );
g_DesignSettings.m_MicroViasMinDrill = diameter;
continue;
}
if( stricmp( Line, "MicroViasAllowed" ) == 0 )
{
g_DesignSettings.m_MicroViasAllowed = atoi( data );
continue;
}
if( stricmp( Line, "TextPcbWidth" ) == 0 )
{
g_DesignSettings.m_PcbTextWidth = atoi( data );
continue;
}
if( stricmp( Line, "TextPcbSize" ) == 0 )
{
g_DesignSettings.m_PcbTextSize.x = atoi( data );
data = strtok( NULL, " =\n\r" );
g_DesignSettings.m_PcbTextSize.y = atoi( data );
continue;
}
if( stricmp( Line, "EdgeModWidth" ) == 0 )
{
ModuleSegmentWidth = atoi( data );
continue;
}
if( stricmp( Line, "TextModWidth" ) == 0 )
{
ModuleTextWidth = atoi( data );
continue;
}
if( stricmp( Line, "TextModSize" ) == 0 )
{
ModuleTextSize.x = atoi( data );
data = strtok( NULL, " =\n\r" );
ModuleTextSize.y = atoi( data );
continue;
}
if( stricmp( Line, "PadSize" ) == 0 )
{
g_Pad_Master.m_Size.x = atoi( data );
data = strtok( NULL, " =\n\r" );
g_Pad_Master.m_Size.y = atoi( data );
continue;
}
if( stricmp( Line, "PadDrill" ) == 0 )
{
g_Pad_Master.m_Drill.x = atoi( data );
g_Pad_Master.m_Drill.y = g_Pad_Master.m_Drill.x;
continue;
}
if( stricmp( Line, "Pad2MaskClearance" ) == 0 )
{
g_DesignSettings.m_MaskMargin = atoi( data );
continue;
}
#endif
}
/* Ensure tracks and vias sizes lists are ok:
* Sort lists by by increasing value and remove duplicates
* (the first value is not tested, because it is the netclass value
*/
sort( GetBoard()->m_ViasDimensionsList.begin()+1, GetBoard()->m_ViasDimensionsList.end() );
sort( GetBoard()->m_TrackWidthList.begin()+1, GetBoard()->m_TrackWidthList.end() );
for( unsigned ii = 1; ii < GetBoard()->m_ViasDimensionsList.size()-1; ii++ )
{
if( GetBoard()->m_ViasDimensionsList[ii] == GetBoard()->m_ViasDimensionsList[ii+1] )
{
GetBoard()->m_ViasDimensionsList.erase(GetBoard()->m_ViasDimensionsList.begin()+ii);
ii--;
}
}
for( unsigned ii = 1; ii < GetBoard()->m_TrackWidthList.size()-1; ii++ )
{
if( GetBoard()->m_TrackWidthList[ii] == GetBoard()->m_TrackWidthList[ii+1] )
{
GetBoard()->m_TrackWidthList.erase(GetBoard()->m_TrackWidthList.begin()+ii);
ii--;
}
}
return 1;
}
#ifdef PCBNEW
2008-03-04 04:22:27 +00:00
/******************************************************************************/
static int WriteSetup( FILE* aFile, WinEDA_BasePcbFrame* aFrame, BOARD* aBoard )
/******************************************************************************/
{
NETCLASS * netclass_default = aFrame->GetBoard()->m_NetClasses.GetDefault();
char text[1024];
2008-03-01 13:15:41 +00:00
fprintf( aFile, "$SETUP\n" );
sprintf( text, "InternalUnit %f INCH\n", 1.0 / PCB_INTERNAL_UNIT );
fprintf( aFile, "%s", text );
2008-03-01 13:15:41 +00:00
fprintf( aFile, "ZoneGridSize %d\n", g_GridRoutingSize );
2008-03-01 13:15:41 +00:00
fprintf( aFile, "Layers %d\n", aBoard->GetCopperLayerCount() );
2008-05-01 06:21:07 +00:00
2008-05-02 05:15:48 +00:00
unsigned layerMask = g_TabAllCopperLayerMask[aBoard->GetCopperLayerCount()-1];
2008-05-01 06:21:07 +00:00
for( int layer=0; layerMask; ++layer, layerMask>>=1 )
2008-03-01 13:15:41 +00:00
{
2008-05-01 06:21:07 +00:00
if( layerMask & 1 )
{
fprintf( aFile, "Layer[%d] %s %s\n", layer,
CONV_TO_UTF8( aBoard->GetLayerName(layer) ),
LAYER::ShowType( aBoard->GetLayerType( layer ) ) );
}
2008-03-01 13:15:41 +00:00
}
// Save current default track width, for compatibility with older pcbnew version;
fprintf( aFile, "TrackWidth %d\n", aBoard->GetCurrentTrackWidth() );
// 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++ )
fprintf( aFile, "TrackWidthList %d\n", aBoard->m_TrackWidthList[ii] );
fprintf( aFile, "TrackClearence %d\n", netclass_default->GetClearance() );
2008-10-23 10:26:06 +00:00
fprintf( aFile, "ZoneClearence %d\n", g_Zone_Default_Setting.m_ZoneClearance );
fprintf( aFile, "TrackMinWidth %d\n" , g_DesignSettings.m_TrackMinWidth );
2008-03-01 13:15:41 +00:00
fprintf( aFile, "DrawSegmWidth %d\n", g_DesignSettings.m_DrawSegmentWidth );
fprintf( aFile, "EdgeSegmWidth %d\n", g_DesignSettings.m_EdgeSegmentWidth );
// Save current default via size, for compatibility with older pcbnew version;
fprintf( aFile, "ViaSize %d\n", netclass_default->GetViaDiameter() );
fprintf( aFile, "ViaDrill %d\n", netclass_default->GetViaDrill() );
fprintf( aFile, "ViaMinSize %d\n", g_DesignSettings.m_ViasMinSize );
fprintf( aFile, "ViaMinDrill %d\n", g_DesignSettings.m_ViasMinDrill );
// 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++ )
fprintf( aFile, "ViaSizeList %d %d\n",
aBoard->m_ViasDimensionsList[ii].m_Diameter,
aBoard->m_ViasDimensionsList[ii].m_Drill );
// for old versions compatibility:
fprintf( aFile, "MicroViaSize %d\n", netclass_default->GetuViaDiameter() );
fprintf( aFile, "MicroViaDrill %d\n", netclass_default->GetuViaDrill());
2008-03-01 13:15:41 +00:00
fprintf( aFile, "MicroViasAllowed %d\n", g_DesignSettings.m_MicroViasAllowed);
fprintf( aFile, "MicroViaMinSize %d\n" , g_DesignSettings.m_MicroViasMinSize );
fprintf( aFile, "MicroViaMinDrill %d\n", g_DesignSettings.m_MicroViasMinDrill );
2008-03-01 13:15:41 +00:00
fprintf( aFile, "TextPcbWidth %d\n", g_DesignSettings.m_PcbTextWidth );
fprintf( aFile, "TextPcbSize %d %d\n",
g_DesignSettings.m_PcbTextSize.x, g_DesignSettings.m_PcbTextSize.y );
2008-03-01 13:15:41 +00:00
fprintf( aFile, "EdgeModWidth %d\n", ModuleSegmentWidth );
fprintf( aFile, "TextModSize %d %d\n", ModuleTextSize.x, ModuleTextSize.y );
fprintf( aFile, "TextModWidth %d\n", ModuleTextWidth );
fprintf( aFile, "PadSize %d %d\n", g_Pad_Master.m_Size.x, g_Pad_Master.m_Size.y );
fprintf( aFile, "PadDrill %d\n", g_Pad_Master.m_Drill.x );
fprintf( aFile, "Pad2MaskClearance %d\n", g_DesignSettings.m_MaskMargin );
2008-03-01 13:15:41 +00:00
fprintf( aFile, "AuxiliaryAxisOrg %d %d\n",
aFrame->m_Auxiliary_Axis_Position.x, aFrame->m_Auxiliary_Axis_Position.y );
fprintf( aFile, "$EndSETUP\n\n" );
return 1;
}
#endif
/******************************************************/
bool WinEDA_PcbFrame::WriteGeneralDescrPcb( FILE* File )
/******************************************************/
{
EDA_BaseStruct* PtStruct = GetBoard()->m_Modules;
int NbModules, NbDrawItem, NbLayers;
/* Write copper layer count */
2009-10-28 11:48:47 +00:00
NbLayers = GetBoard()->m_BoardSettings->GetCopperLayerCount();
fprintf( File, "$GENERAL\n" );
fprintf( File, "LayerCount %d\n", NbLayers );
// Write old format for Layer count (for compatibility with old versions of pcbnew
fprintf( File, "Ly %8X\n", g_TabAllCopperLayerMask[NbLayers - 1] | ALL_NO_CU_LAYERS ); // For compatibility with old version of pcbnew
fprintf( File, "EnabledLayers %08X\n", GetBoard()->GetEnabledLayers() );
fprintf( File, "VisibleLayers %08X\n", GetBoard()->GetVisibleLayers() );
fprintf( File, "VisibleElements %08X\n", GetBoard()->GetVisibleElements() );
fprintf( File, "Links %d\n", GetBoard()->GetRatsnestsCount() );
fprintf( File, "NoConn %d\n", GetBoard()->m_NbNoconnect );
/* Write Bounding box info */
GetBoard()->ComputeBoundaryBox();
fprintf( File, "Di %d %d %d %d\n",
GetBoard()->m_BoundaryBox.GetX(), GetBoard()->m_BoundaryBox.GetY(),
GetBoard()->m_BoundaryBox.GetRight(),
GetBoard()->m_BoundaryBox.GetBottom() );
/* Write segment count for footprints, drawings, track and zones */
/* Calculate the footprint count */
for( NbModules = 0; PtStruct != NULL; PtStruct = PtStruct->Next() )
NbModules++;
PtStruct = GetBoard()->m_Drawings; NbDrawItem = 0;
for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
NbDrawItem++;
fprintf( File, "Ndraw %d\n", NbDrawItem );
fprintf( File, "Ntrack %d\n", GetBoard()->GetNumSegmTrack() );
fprintf( File, "Nzone %d\n", GetBoard()->GetNumSegmZone() );
fprintf( File, "LayerThickness %d\n", GetBoard()->m_BoardSettings->m_LayerThickness );
fprintf( File, "Nmodule %d\n", NbModules );
2009-08-17 02:59:38 +00:00
fprintf( File, "Nnets %d\n", GetBoard()->m_NetInfo->GetCount() );
fprintf( File, "$EndGENERAL\n\n" );
return TRUE;
}
/******************************************************/
bool WriteSheetDescr( BASE_SCREEN* screen, FILE* File )
/******************************************************/
/** Function WriteSheetDescr
* Save the page information (size, texts, date ..)
* @param screen BASE_SCREEN to save
* @param File = an openen FILE to write info
*/
{
Ki_PageDescr* sheet = screen->m_CurrentSheetDesc;
fprintf( File, "$SHEETDESCR\n" );
fprintf( File, "Sheet %s %d %d\n",
CONV_TO_UTF8( sheet->m_Name ), sheet->m_Size.x, sheet->m_Size.y );
fprintf( File, "Title \"%s\"\n", CONV_TO_UTF8( screen->m_Title ) );
fprintf( File, "Date \"%s\"\n", CONV_TO_UTF8( screen->m_Date ) );
fprintf( File, "Rev \"%s\"\n", CONV_TO_UTF8( screen->m_Revision ) );
fprintf( File, "Comp \"%s\"\n", CONV_TO_UTF8( screen->m_Company ) );
fprintf( File, "Comment1 \"%s\"\n", CONV_TO_UTF8( screen->m_Commentaire1 ) );
fprintf( File, "Comment2 \"%s\"\n", CONV_TO_UTF8( screen->m_Commentaire2 ) );
fprintf( File, "Comment3 \"%s\"\n", CONV_TO_UTF8( screen->m_Commentaire3 ) );
fprintf( File, "Comment4 \"%s\"\n", CONV_TO_UTF8( screen->m_Commentaire4 ) );
fprintf( File, "$EndSHEETDESCR\n\n" );
return TRUE;
}
/***************************************************************************/
static bool ReadSheetDescr( BASE_SCREEN* screen, FILE* File, int* LineNum )
/***************************************************************************/
{
char Line[1024], buf[1024], * text;
while( GetLine( File, Line, LineNum ) != NULL )
{
if( strnicmp( Line, "$End", 4 ) == 0 )
return TRUE;
if( strnicmp( Line, "Sheet", 4 ) == 0 )
{
text = strtok( Line, " \t\n\r" );
text = strtok( NULL, " \t\n\r" );
Ki_PageDescr* sheet = g_SheetSizeList[0];
int ii;
for( ii = 0; sheet != NULL; ii++, sheet = g_SheetSizeList[ii] )
{
if( stricmp( CONV_TO_UTF8( sheet->m_Name ), text ) == 0 )
{
screen->m_CurrentSheetDesc = sheet;
if( sheet == &g_Sheet_user )
{
text = strtok( NULL, " \t\n\r" );
if( text )
sheet->m_Size.x = atoi( text );
text = strtok( NULL, " \t\n\r" );
if( text )
sheet->m_Size.y = atoi( text );
}
break;
}
}
continue;
}
if( strnicmp( Line, "Title", 2 ) == 0 )
{
ReadDelimitedText( buf, Line, 256 );
screen->m_Title = CONV_FROM_UTF8( buf );
continue;
}
if( strnicmp( Line, "Date", 2 ) == 0 )
{
ReadDelimitedText( buf, Line, 256 );
screen->m_Date = CONV_FROM_UTF8( buf );
continue;
}
if( strnicmp( Line, "Rev", 2 ) == 0 )
{
ReadDelimitedText( buf, Line, 256 );
screen->m_Revision = CONV_FROM_UTF8( buf );
continue;
}
if( strnicmp( Line, "Comp", 4 ) == 0 )
{
ReadDelimitedText( buf, Line, 256 );
screen->m_Company = CONV_FROM_UTF8( buf );
continue;
}
if( strnicmp( Line, "Comment1", 8 ) == 0 )
{
ReadDelimitedText( buf, Line, 256 );
screen->m_Commentaire1 = CONV_FROM_UTF8( buf );
continue;
}
if( strnicmp( Line, "Comment2", 8 ) == 0 )
{
ReadDelimitedText( buf, Line, 256 );
screen->m_Commentaire2 = CONV_FROM_UTF8( buf );
continue;
}
if( strnicmp( Line, "Comment3", 8 ) == 0 )
{
ReadDelimitedText( buf, Line, 256 );
screen->m_Commentaire3 = CONV_FROM_UTF8( buf );
continue;
}
if( strnicmp( Line, "Comment4", 8 ) == 0 )
{
ReadDelimitedText( buf, Line, 256 );
screen->m_Commentaire4 = CONV_FROM_UTF8( buf );
continue;
}
}
return FALSE;
}
/********************************************************************/
int WinEDA_PcbFrame::ReadPcbFile( FILE* File, bool Append )
/********************************************************************/
/** ReadPcbFile
* Read a board file <file>.brd
* @param Append if 0: a previoulsy loaded board is deleted before loading the file.
* else all items of the board file are added to the existing board
*/
{
char Line[1024];
int LineNum = 0;
wxBusyCursor dummy;
// Switch the locale to standard C (needed to read floating point numbers like 1.3)
2009-08-17 02:59:38 +00:00
SetLocaleTo_C_standard();
BOARD* board = GetBoard();
NbDraw = NbTrack = NbZone = NbMod = NbNets = -1;
2009-08-17 02:59:38 +00:00
board->m_Status_Pcb = 0;
board->m_NetClasses.Clear();
2009-09-10 15:22:26 +00:00
// Put a dollar sign in front, and test for a specific length of characters
// The -1 is to omit the trailing \0 which is included in sizeof() on a string.
#define TESTLINE(x) (strncmp(Line, "$" x, sizeof("$" x)-1) == 0)
while( GetLine( File, Line, &LineNum ) != NULL )
{
2009-09-10 15:22:26 +00:00
// put the more frequent ones at the top
2009-09-10 15:22:26 +00:00
if( TESTLINE( "MODULE" ) )
{
2009-09-10 15:22:26 +00:00
MODULE* Module = new MODULE( board );
2009-09-10 15:22:26 +00:00
if( Module == NULL )
continue;
board->Add( Module, ADD_APPEND );
Module->ReadDescr( File, &LineNum );
continue;
}
2009-09-10 15:22:26 +00:00
if( TESTLINE( "DRAWSEGMENT" ) )
{
2009-09-10 15:22:26 +00:00
DRAWSEGMENT* DrawSegm = new DRAWSEGMENT( board );
board->Add( DrawSegm, ADD_APPEND );
DrawSegm->ReadDrawSegmentDescr( File, &LineNum );
continue;
}
2009-09-10 15:22:26 +00:00
if( TESTLINE( "EQUIPOT" ) )
{
2009-08-17 02:59:38 +00:00
NETINFO_ITEM* net = new NETINFO_ITEM( board );
board->m_NetInfo->AppendNet( net );
net->ReadDescr( File, &LineNum );
continue;
}
2009-09-10 15:22:26 +00:00
if( TESTLINE( "TEXTPCB" ) )
{
2009-09-10 15:22:26 +00:00
TEXTE_PCB* pcbtxt = new TEXTE_PCB( board );
board->Add( pcbtxt, ADD_APPEND );
pcbtxt->ReadTextePcbDescr( File, &LineNum );
continue;
}
2009-09-10 15:22:26 +00:00
if( TESTLINE( "TRACK" ) )
{
2009-09-10 15:22:26 +00:00
#ifdef PCBNEW
TRACK* insertBeforeMe = Append ? NULL : board->m_Track.GetFirst();
ReadListeSegmentDescr( File, insertBeforeMe, TYPE_TRACK,
&LineNum, NbTrack );
#endif
2008-02-07 06:49:16 +00:00
continue;
2008-03-01 13:15:41 +00:00
}
2009-09-10 15:22:26 +00:00
if( TESTLINE( BRD_NETCLASS ) )
{
2009-09-10 15:22:26 +00:00
// create an empty NETCLASS without a name.
NETCLASS* netclass = new NETCLASS( board, wxEmptyString );
2009-09-10 15:22:26 +00:00
// fill it from the *.brd file, and establish its name.
netclass->ReadDescr( File, &LineNum );
2009-09-10 15:22:26 +00:00
if( !board->m_NetClasses.Add( netclass ) )
{
// Must have been a name conflict, this is a bad board file.
// User may have done a hand edit to the file.
// Delete netclass if board could not take ownership of it.
delete netclass;
// @todo: throw an exception here, this is a bad board file.
}
continue;
}
2009-09-10 15:22:26 +00:00
if( TESTLINE( "CZONE_OUTLINE" ) )
{
2009-09-10 15:22:26 +00:00
ZONE_CONTAINER * zone_descr = new ZONE_CONTAINER(board);
zone_descr->ReadDescr( File, &LineNum );
if ( zone_descr->GetNumCorners( ) > 2 ) // should always occur
board->Add(zone_descr);
else delete zone_descr;
continue;
}
2009-09-10 15:22:26 +00:00
if( TESTLINE( "COTATION" ) )
{
2009-08-17 02:59:38 +00:00
COTATION* Cotation = new COTATION( board );
board->Add( Cotation, ADD_APPEND );
Cotation->ReadCotationDescr( File, &LineNum );
continue;
}
2009-09-10 15:22:26 +00:00
if( TESTLINE( "MIREPCB" ) )
{
2009-08-17 02:59:38 +00:00
MIREPCB* Mire = new MIREPCB( board );
board->Add( Mire, ADD_APPEND );
Mire->ReadMirePcbDescr( File, &LineNum );
continue;
}
2009-09-10 15:22:26 +00:00
if( TESTLINE( "ZONE" ) )
{
#ifdef PCBNEW
2009-09-10 15:22:26 +00:00
SEGZONE* insertBeforeMe = Append ? NULL : board->m_Zone.GetFirst();
ReadListeSegmentDescr( File, insertBeforeMe, TYPE_ZONE,
&LineNum, NbZone );
#endif
continue;
}
2009-09-10 15:22:26 +00:00
if( TESTLINE( "GENERAL" ) )
{
2009-09-10 15:22:26 +00:00
ReadGeneralDescrPcb( File, &LineNum );
continue;
}
2009-09-10 15:22:26 +00:00
if( TESTLINE( "SHEETDESCR" ) )
{
ReadSheetDescr( GetScreen(), File, &LineNum );
continue;
}
2009-09-10 15:22:26 +00:00
if( TESTLINE( "SETUP" ) )
{
if( !Append )
{
ReadSetup( File, &LineNum );
}
else
{
while( GetLine( File, Line, &LineNum ) != NULL )
if( TESTLINE( "EndSETUP" ) )
break;
}
continue;
}
if( TESTLINE( "EndPCB" ) )
break;
}
2008-06-06 16:39:45 +00:00
SetLocaleTo_Default( ); // revert to the current locale
GetBoard()->m_Status_Pcb = 0;
// Build the net info list
GetBoard()->m_NetInfo->BuildListOfNets();
2009-08-17 02:59:38 +00:00
board->SynchronizeNetsAndNetClasses( );
2009-10-07 17:10:37 +00:00
m_TrackAndViasSizesList_Changed = true;
Affiche_Message( wxEmptyString );
BestZoom();
SetToolbars();
return 1;
}
#ifdef PCBNEW
/***************************************************/
2007-10-30 21:30:58 +00:00
int WinEDA_PcbFrame::SavePcbFormatAscii( FILE* aFile )
/****************************************************/
/* Routine de sauvegarde du PCB courant sous format ASCII
* retourne
* 1 si OK
* 0 si sauvegarde non faite
*/
{
2007-10-30 21:30:58 +00:00
bool rc;
char line[256];
2008-03-01 13:15:41 +00:00
GetBoard()->m_Status_Pcb &= ~CONNEXION_OK;
2007-10-30 21:30:58 +00:00
wxBeginBusyCursor();
2008-03-01 13:15:41 +00:00
// Switch the locale to standard C (needed to print floating point numbers like 1.3)
2008-06-06 16:39:45 +00:00
SetLocaleTo_C_standard( );
2008-03-01 13:15:41 +00:00
2007-10-30 21:30:58 +00:00
/* Ecriture de l'entete PCB : */
fprintf( aFile, "PCBNEW-BOARD Version %d date %s\n\n", g_CurrentVersionPCB,
DateAndTime( line ) );
2009-05-21 14:59:54 +00:00
fprintf( aFile, "# Created by Pcbnew%s\n\n", CONV_TO_UTF8( GetBuildVersion() ) );
GetBoard()->SynchronizeNetsAndNetClasses();
// Select default Netclass before writing file.
// Useful to save default values in headers
GetBoard()->SetCurrentNetClass( GetBoard()->m_NetClasses.GetDefault()->GetName( ));
m_TrackAndViasSizesList_Changed = true;
AuxiliaryToolBar_Update_UI();
2007-10-30 21:30:58 +00:00
WriteGeneralDescrPcb( aFile );
WriteSheetDescr( GetScreen(), aFile );
WriteSetup( aFile, this, GetBoard() );
rc = GetBoard()->Save( aFile );
2008-03-01 13:15:41 +00:00
2008-06-06 16:39:45 +00:00
SetLocaleTo_Default( ); // revert to the current locale
2007-10-30 21:30:58 +00:00
wxEndBusyCursor();
2008-03-01 13:15:41 +00:00
2007-10-30 21:30:58 +00:00
if( !rc )
DisplayError( this, wxT( "Unable to save PCB file" ) );
else
Affiche_Message( wxEmptyString );
2008-03-01 13:15:41 +00:00
2007-10-30 21:30:58 +00:00
return rc;
}
#endif