From c4979318d265cf85b7fe758d3e981f11671d3df6 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Tue, 6 Dec 2011 23:28:49 -0600 Subject: [PATCH] more plugin work --- CMakeLists.txt | 3 + CMakeModules/config.h.cmake | 3 + common/CMakeLists.txt | 8 + cvpcb/CMakeLists.txt | 3 +- pcbnew/CMakeLists.txt | 2 - pcbnew/class_board.cpp | 83 -- pcbnew/class_dimension.cpp | 197 --- pcbnew/class_drawsegment.cpp | 111 -- pcbnew/class_edge_mod.cpp | 184 --- pcbnew/class_mire.cpp | 56 - pcbnew/class_module.cpp | 391 ------ pcbnew/class_netclass.cpp | 127 -- pcbnew/class_netinfo_item.cpp | 53 - pcbnew/class_pad.cpp | 253 ---- pcbnew/class_pcb_text.cpp | 165 --- pcbnew/class_text_mod.cpp | 119 -- pcbnew/class_track.cpp | 18 - pcbnew/class_zone.cpp | 404 ------ pcbnew/files.cpp | 2 +- pcbnew/ioascii.cpp | 5 +- pcbnew/item_io.cpp | 2213 +++++++++++++++++++++++++++++++++ pcbnew/kicad_plugin.cpp | 863 ++++++++++++- pcbnew/kicad_plugin.h | 1 + pcbnew/loadcmp.cpp | 128 +- 24 files changed, 3163 insertions(+), 2229 deletions(-) create mode 100644 pcbnew/item_io.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b0b01aa86..e6ea644c70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,9 @@ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules) option(USE_PNG_BITMAPS "use PNG bitmaps instead of XPM (default ON)" ON) +option(USE_NEW_PCBNEW_LOAD "use new plugin support for legacy file format (default OFF)" OFF) +option(USE_NEW_PCBNEW_SAVE "use new plugin support for legacy file format (default OFF)" OFF) + # Russian GOST patch option(wxUSE_UNICODE "enable/disable building unicode (default OFF)") option(KICAD_GOST "enable/disable building using GOST notation for multiple gates per package (default OFF)") diff --git a/CMakeModules/config.h.cmake b/CMakeModules/config.h.cmake index d47f9b63a3..fe41c91da7 100644 --- a/CMakeModules/config.h.cmake +++ b/CMakeModules/config.h.cmake @@ -54,4 +54,7 @@ #cmakedefine USE_PNG_BITMAPS 1 +#cmakedefine USE_NEW_PCBNEW_LOAD +#cmakedefine USE_NEW_PCBNEW_SAVE + #endif /* __CONFIG_H__ */ diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 36ffb30597..afac4eb1d9 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -107,6 +107,14 @@ set(PCB_COMMON_SRCS ../pcbnew/sel_layer.cpp ) + +if ( USE_NEW_PCBNEW_LOAD OR USE_NEW_PCBNEW_SAVE ) + set( PCB_COMMON_SRCS ${PCB_COMMON_SRCS} ../pcbnew/item_io.cpp ../pcbnew/io_mgr.cpp ../pcbnew/kicad_plugin.cpp ) +else() + set( PCB_COMMON_SRCS ${PCB_COMMON_SRCS} ../pcbnew/item_io.cpp ) +endif() + + add_library(pcbcommon ${PCB_COMMON_SRCS}) # auto-generate netlist_lexer.h and netlist_keywords.cpp diff --git a/cvpcb/CMakeLists.txt b/cvpcb/CMakeLists.txt index a66ca9a524..6af9552691 100644 --- a/cvpcb/CMakeLists.txt +++ b/cvpcb/CMakeLists.txt @@ -39,7 +39,8 @@ set(CVPCB_SRCS savecmp.cpp setvisu.cpp tool_cvpcb.cpp - writenetlistpcbnew.cpp) + writenetlistpcbnew.cpp + ) ### # Windows resource file diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index d7c30627d7..ca05e4661f 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -126,9 +126,7 @@ set(PCBNEW_SRCS hotkeys_board_editor.cpp hotkeys_module_editor.cpp initpcb.cpp - io_mgr.cpp ioascii.cpp - kicad_plugin.cpp layer_widget.cpp librairi.cpp loadcmp.cpp diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index b852d9fe3b..4270d2f96b 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -1394,89 +1394,6 @@ int BOARD::ReturnSortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCoun } -bool BOARD::Save( FILE* aFile ) const -{ - bool rc = false; - BOARD_ITEM* item; - - // save the nets - for( unsigned ii = 0; ii < m_NetInfo->GetCount(); ii++ ) - if( !m_NetInfo->GetNetItem( ii )->Save( aFile ) ) - goto out; - - // Saved nets do not include netclass names, so save netclasses after nets. - m_NetClasses.Save( aFile ); - - // save the modules - for( item = m_Modules; item; item = item->Next() ) - if( !item->Save( aFile ) ) - goto out; - - for( item = m_Drawings; item; item = item->Next() ) - { - switch( item->Type() ) - { - case PCB_TEXT_T: - case PCB_LINE_T: - case PCB_TARGET_T: - case PCB_DIMENSION_T: - if( !item->Save( aFile ) ) - goto out; - - break; - - default: - - // future: throw exception here -#if defined(DEBUG) - printf( "BOARD::Save() ignoring m_Drawings type %d\n", item->Type() ); -#endif - break; - } - } - - // do not save MARKER_PCBs, they can be regenerated easily - - // save the tracks & vias - fprintf( aFile, "$TRACK\n" ); - - for( item = m_Track; item; item = item->Next() ) - { - if( !item->Save( aFile ) ) - goto out; - } - - fprintf( aFile, "$EndTRACK\n" ); - - // save the zones - fprintf( aFile, "$ZONE\n" ); - - for( item = m_Zone; item; item = item->Next() ) - { - if( !item->Save( aFile ) ) - goto out; - } - - fprintf( aFile, "$EndZONE\n" ); - - // save the zone edges - for( unsigned ii = 0; ii < m_ZoneDescriptorList.size(); ii++ ) - { - ZONE_CONTAINER* edge_zone = m_ZoneDescriptorList[ii]; - edge_zone->Save( aFile ); - } - - - if( fprintf( aFile, "$EndBOARD\n" ) != sizeof("$EndBOARD\n") - 1 ) - goto out; - - rc = true; // wrote all OK - -out: - return rc; -} - - void BOARD::RedrawAreasOutlines( EDA_DRAW_PANEL* panel, wxDC* aDC, int aDrawMode, int aLayer ) { if( !aDC ) diff --git a/pcbnew/class_dimension.cpp b/pcbnew/class_dimension.cpp index 26189379b6..d10ab67d92 100644 --- a/pcbnew/class_dimension.cpp +++ b/pcbnew/class_dimension.cpp @@ -105,137 +105,6 @@ void DIMENSION::Copy( DIMENSION* source ) } -bool DIMENSION::ReadDimensionDescr( LINE_READER* aReader ) -{ - char* Line; - char Text[2048]; - - while( aReader->ReadLine() ) - { - Line = aReader->Line(); - - if( strnicmp( Line, "$EndDIMENSION", 4 ) == 0 ) - return true; - - if( Line[0] == 'V' ) - { - sscanf( Line + 2, " %d", &m_Value ); - continue; - } - - if( Line[0] == 'G' ) - { - int layer; - - sscanf( Line + 2, " %d %d %lX", &m_Shape, &layer, &m_TimeStamp ); - - if( layer < FIRST_NO_COPPER_LAYER ) - layer = FIRST_NO_COPPER_LAYER; - - if( layer > LAST_NO_COPPER_LAYER ) - layer = LAST_NO_COPPER_LAYER; - - SetLayer( layer ); - m_Text->SetLayer( layer ); - continue; - } - - if( Line[0] == 'T' ) - { - ReadDelimitedText( Text, Line + 2, sizeof(Text) ); - m_Text->m_Text = FROM_UTF8( Text ); - continue; - } - - if( Line[0] == 'P' ) - { - int normal_display = 1; - int orientation; - int thickness; - sscanf( Line + 2, " %d %d %d %d %d %d %d", - &m_Text->m_Pos.x, &m_Text->m_Pos.y, - &m_Text->m_Size.x, &m_Text->m_Size.y, - &thickness, &orientation, - &normal_display ); - - m_Text->m_Mirror = normal_display ? false : true; - m_Pos = m_Text->m_Pos; - m_Text->SetOrientation( orientation ); - m_Text->SetThickness( thickness ); - continue; - } - - if( Line[0] == 'S' ) - { - switch( Line[1] ) - { - int Dummy; - - case 'b': - sscanf( Line + 2, " %d %d %d %d %d %d", - &Dummy, - &m_crossBarOx, &m_crossBarOy, - &m_crossBarFx, &m_crossBarFy, - &m_Width ); - break; - - case 'd': - sscanf( Line + 2, " %d %d %d %d %d %d", - &Dummy, - &m_featureLineDOx, &m_featureLineDOy, - &m_featureLineDFx, &m_featureLineDFy, - &Dummy ); - break; - - case 'g': - sscanf( Line + 2, " %d %d %d %d %d %d", - &Dummy, - &m_featureLineGOx, &m_featureLineGOy, - &m_featureLineGFx, &m_featureLineGFy, - &Dummy ); - break; - - case '1': - sscanf( Line + 2, " %d %d %d %d %d %d", - &Dummy, - &m_arrowD1Ox, &m_arrowD1Oy, - &m_arrowD1Fx, &m_arrowD1Fy, - &Dummy ); - break; - - case '2': - sscanf( Line + 2, " %d %d %d %d %d %d", - &Dummy, - &m_arrowD2Ox, &m_arrowD2Oy, - &m_arrowD2Fx, &m_arrowD2Fy, - &Dummy ); - break; - - case '3': - sscanf( Line + 2, " %d %d %d %d %d %d\n", - &Dummy, - &m_arrowG1Ox, &m_arrowG1Oy, - &m_arrowG1Fx, &m_arrowG1Fy, - &Dummy ); - break; - - case '4': - sscanf( Line + 2, " %d %d %d %d %d %d", - &Dummy, - &m_arrowG2Ox, &m_arrowG2Oy, - &m_arrowG2Fx, &m_arrowG2Fy, - &Dummy ); - break; - } - - continue; - } - } - - return false; -} - - void DIMENSION::Move(const wxPoint& offset) { m_Pos += offset; @@ -344,72 +213,6 @@ void DIMENSION::Mirror(const wxPoint& axis_pos) } -bool DIMENSION::Save( FILE* aFile ) const -{ - bool rc = false; - - // note: COTATION was the previous name of DIMENSION - // this old keyword is used here for compatibility - const char keyWordLine[] = "$COTATION\n"; - const char keyWordLineEnd[] = "$endCOTATION\n"; - - if( fputs( keyWordLine, aFile ) == EOF ) - goto out; - - fprintf( aFile, "Ge %d %d %lX\n", m_Shape, m_Layer, m_TimeStamp ); - - fprintf( aFile, "Va %d\n", m_Value ); - - if( !m_Text->m_Text.IsEmpty() ) - fprintf( aFile, "Te %s\n", EscapedUTF8( m_Text->m_Text ).c_str() ); - else - fprintf( aFile, "Te \"?\"\n" ); - - fprintf( aFile, "Po %d %d %d %d %d %d %d\n", - m_Text->m_Pos.x, m_Text->m_Pos.y, - m_Text->m_Size.x, m_Text->m_Size.y, - m_Text->GetThickness(), m_Text->GetOrientation(), - m_Text->m_Mirror ? 0 : 1 ); - - fprintf( aFile, "Sb %d %d %d %d %d %d\n", S_SEGMENT, - m_crossBarOx, m_crossBarOy, - m_crossBarFx, m_crossBarFy, m_Width ); - - fprintf( aFile, "Sd %d %d %d %d %d %d\n", S_SEGMENT, - m_featureLineDOx, m_featureLineDOy, - m_featureLineDFx, m_featureLineDFy, m_Width ); - - fprintf( aFile, "Sg %d %d %d %d %d %d\n", S_SEGMENT, - m_featureLineGOx, m_featureLineGOy, - m_featureLineGFx, m_featureLineGFy, m_Width ); - - fprintf( aFile, "S1 %d %d %d %d %d %d\n", S_SEGMENT, - m_arrowD1Ox, m_arrowD1Oy, - m_arrowD1Fx, m_arrowD1Fy, m_Width ); - - fprintf( aFile, "S2 %d %d %d %d %d %d\n", S_SEGMENT, - m_arrowD2Ox, m_arrowD2Oy, - m_arrowD2Fx, m_arrowD2Fy, m_Width ); - - - fprintf( aFile, "S3 %d %d %d %d %d %d\n", S_SEGMENT, - m_arrowG1Ox, m_arrowG1Oy, - m_arrowG1Fx, m_arrowG1Fy, m_Width ); - - fprintf( aFile, "S4 %d %d %d %d %d %d\n", S_SEGMENT, - m_arrowG2Ox, m_arrowG2Oy, - m_arrowG2Fx, m_arrowG2Fy, m_Width ); - - if( fputs( keyWordLineEnd, aFile ) == EOF ) - goto out; - - rc = true; - -out: - return rc; -} - - void DIMENSION::AdjustDimensionDetails( bool aDoNotChangeText ) { #define ARROW_SIZE 500 //size of arrows diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp index 1f74f64023..61974753ca 100644 --- a/pcbnew/class_drawsegment.cpp +++ b/pcbnew/class_drawsegment.cpp @@ -74,117 +74,6 @@ void DRAWSEGMENT::Flip( const wxPoint& aCentre ) } -bool DRAWSEGMENT::Save( FILE* aFile ) const -{ - if( fprintf( aFile, "$DRAWSEGMENT\n" ) != sizeof("$DRAWSEGMENT\n") - 1 ) - return false; - - fprintf( aFile, "Po %d %d %d %d %d %d\n", - m_Shape, - m_Start.x, m_Start.y, - m_End.x, m_End.y, m_Width ); - - if( m_Type != S_CURVE ) - { - fprintf( aFile, "De %d %d %d %lX %X\n", - m_Layer, m_Type, m_Angle, - m_TimeStamp, ReturnStatus() ); - } - else - { - fprintf( aFile, "De %d %d %d %lX %X %d %d %d %d\n", - m_Layer, m_Type, m_Angle, - m_TimeStamp, ReturnStatus(), - m_BezierC1.x,m_BezierC1.y, - m_BezierC2.x,m_BezierC2.y); - } - - if( fprintf( aFile, "$EndDRAWSEGMENT\n" ) != sizeof("$EndDRAWSEGMENT\n") - 1 ) - return false; - - return true; -} - - -bool DRAWSEGMENT::ReadDrawSegmentDescr( LINE_READER* aReader ) -{ - char* Line; - - while( aReader->ReadLine() ) - { - Line = aReader->Line(); - - if( strnicmp( Line, "$End", 4 ) == 0 ) - return true; /* End of description */ - - if( Line[0] == 'P' ) - { - sscanf( Line + 2, " %d %d %d %d %d %d", - &m_Shape, &m_Start.x, &m_Start.y, - &m_End.x, &m_End.y, &m_Width ); - - if( m_Width < 0 ) - m_Width = 0; - } - - if( Line[0] == 'D' ) - { - int status; - char* token = 0; - - token = strtok( Line," " ); - - for( int i = 0; (token = strtok( NULL," " )) != NULL; i++ ) - { - switch( i ) - { - case 0: - sscanf( token,"%d",&m_Layer ); - break; - case 1: - sscanf( token,"%d",&m_Type ); - break; - case 2: - sscanf( token,"%d",&m_Angle ); - break; - case 3: - sscanf( token,"%lX",&m_TimeStamp ); - break; - case 4: - sscanf( token,"%X",&status ); - break; - /* Bezier Control Points*/ - case 5: - sscanf( token,"%d",&m_BezierC1.x ); - break; - case 6: - sscanf( token,"%d",&m_BezierC1.y ); - break; - case 7: - sscanf( token,"%d",&m_BezierC2.x ); - break; - case 8: - sscanf( token,"%d",&m_BezierC2.y ); - break; - default: - break; - } - } - - if( m_Layer < FIRST_NO_COPPER_LAYER ) - m_Layer = FIRST_NO_COPPER_LAYER; - - if( m_Layer > LAST_NO_COPPER_LAYER ) - m_Layer = LAST_NO_COPPER_LAYER; - - SetState( status, ON ); - } - } - - return false; -} - - wxPoint DRAWSEGMENT::GetStart() const { switch( m_Shape ) diff --git a/pcbnew/class_edge_mod.cpp b/pcbnew/class_edge_mod.cpp index a5905dbb3a..4d72b4729b 100644 --- a/pcbnew/class_edge_mod.cpp +++ b/pcbnew/class_edge_mod.cpp @@ -16,16 +16,11 @@ #include "wxBasePcbFrame.h" #include "pcbcommon.h" -#include "pcbnew.h" - #include "class_board.h" #include "class_module.h" #include "class_edge_mod.h" -#define MAX_WIDTH 10000 /* Thickness (in 1 / 10000 ") of maximum reasonable features, text... */ - - /*********************/ /* class EDGE_MODULE */ /*********************/ @@ -238,185 +233,6 @@ void EDGE_MODULE::DisplayInfo( EDA_DRAW_FRAME* frame ) } -bool EDGE_MODULE::Save( FILE* aFile ) const -{ - int ret = -1; - - switch( m_Shape ) - { - case S_SEGMENT: - ret = fprintf( aFile, "DS %d %d %d %d %d %d\n", - m_Start0.x, m_Start0.y, - m_End0.x, m_End0.y, - m_Width, m_Layer ); - break; - - case S_CIRCLE: - ret = fprintf( aFile, "DC %d %d %d %d %d %d\n", - m_Start0.x, m_Start0.y, - m_End0.x, m_End0.y, - m_Width, m_Layer ); - break; - - case S_ARC: - ret = fprintf( aFile, "DA %d %d %d %d %d %d %d\n", - m_Start0.x, m_Start0.y, - m_End0.x, m_End0.y, - m_Angle, - m_Width, m_Layer ); - break; - - case S_POLYGON: - ret = fprintf( aFile, "DP %d %d %d %d %d %d %d\n", - m_Start0.x, m_Start0.y, - m_End0.x, m_End0.y, - (int) m_PolyPoints.size(), - m_Width, m_Layer ); - - for( unsigned i = 0; i 5; -} - - -/* Read a description line like: - * DS 2600 0 2600 -600 120 21 - * this description line is in Line - * EDGE_MODULE type can be: - * - Circle, - * - Segment (line) - * - Arc - * - Polygon - * - */ -int EDGE_MODULE::ReadDescr( LINE_READER* aReader ) -{ - int ii; - int error = 0; - char* Buf; - char* Line; - - Line = aReader->Line(); - - switch( Line[1] ) - { - case 'S': - m_Shape = S_SEGMENT; - break; - - case 'C': - m_Shape = S_CIRCLE; - break; - - case 'A': - m_Shape = S_ARC; - break; - - case 'P': - m_Shape = S_POLYGON; - break; - - default: - wxString msg; - msg.Printf( wxT( "Unknown EDGE_MODULE type <%s>" ), Line ); - DisplayError( NULL, msg ); - error = 1; - break; - } - - switch( m_Shape ) - { - case S_ARC: - sscanf( Line + 3, "%d %d %d %d %d %d %d", - &m_Start0.x, &m_Start0.y, - &m_End0.x, &m_End0.y, - &m_Angle, &m_Width, &m_Layer ); - NORMALIZE_ANGLE_360( m_Angle ); - break; - - case S_SEGMENT: - case S_CIRCLE: - sscanf( Line + 3, "%d %d %d %d %d %d", - &m_Start0.x, &m_Start0.y, - &m_End0.x, &m_End0.y, - &m_Width, &m_Layer ); - break; - - case S_POLYGON: - int pointCount; - sscanf( Line + 3, "%d %d %d %d %d %d %d", - &m_Start0.x, &m_Start0.y, - &m_End0.x, &m_End0.y, - &pointCount, &m_Width, &m_Layer ); - - m_PolyPoints.clear(); - m_PolyPoints.reserve( pointCount ); - - for( ii = 0; iiReadLine() ) - { - Buf = aReader->Line(); - - if( strncmp( Buf, "Dl", 2 ) != 0 ) - { - error = 1; - break; - } - - int x; - int y; - sscanf( Buf + 3, "%d %d\n", &x, &y ); - - m_PolyPoints.push_back( wxPoint( x, y ) ); - } - else - { - error = 1; - break; - } - } - - break; - - default: - sscanf( Line + 3, "%d %d %d %d %d %d", - &m_Start0.x, &m_Start0.y, - &m_End0.x, &m_End0.y, - &m_Width, &m_Layer ); - break; - } - - // Check for a reasonable width: - if( m_Width <= 1 ) - m_Width = 1; - - if( m_Width > MAX_WIDTH ) - m_Width = MAX_WIDTH; - - // Check for a reasonable layer: - // m_Layer must be >= FIRST_NON_COPPER_LAYER, but because microwave footprints - // can use the copper layers m_Layer < FIRST_NON_COPPER_LAYER is allowed. - // @todo: changes use of EDGE_MODULE these footprints and allows only - // m_Layer >= FIRST_NON_COPPER_LAYER - if( (m_Layer < 0) || (m_Layer > LAST_NON_COPPER_LAYER) ) - m_Layer = SILKSCREEN_N_FRONT; - - return error; -} - wxString EDGE_MODULE::GetSelectMenuText() const { diff --git a/pcbnew/class_mire.cpp b/pcbnew/class_mire.cpp index 27437716ba..161c2d7605 100644 --- a/pcbnew/class_mire.cpp +++ b/pcbnew/class_mire.cpp @@ -54,62 +54,6 @@ void PCB_TARGET::Copy( PCB_TARGET* source ) } -/* Read the description from the PCB file. - */ -bool PCB_TARGET::ReadMirePcbDescr( LINE_READER* aReader ) -{ - char* Line; - - while( aReader->ReadLine() ) - { - Line = aReader->Line(); - - if( strnicmp( Line, "$End", 4 ) == 0 ) - return true; - - if( Line[0] == 'P' ) - { - sscanf( Line + 2, " %X %d %d %d %d %d %lX", - &m_Shape, &m_Layer, - &m_Pos.x, &m_Pos.y, - &m_Size, &m_Width, &m_TimeStamp ); - - if( m_Layer < FIRST_NO_COPPER_LAYER ) - m_Layer = FIRST_NO_COPPER_LAYER; - - if( m_Layer > LAST_NO_COPPER_LAYER ) - m_Layer = LAST_NO_COPPER_LAYER; - } - } - - return false; -} - - -bool PCB_TARGET::Save( FILE* aFile ) const -{ - bool rc = false; - - if( fprintf( aFile, "$PCB_TARGET\n" ) != sizeof("$PCB_TARGET\n")-1 ) - goto out; - - fprintf( aFile, "Po %X %d %d %d %d %d %8.8lX\n", - m_Shape, m_Layer, - m_Pos.x, m_Pos.y, - m_Size, m_Width, m_TimeStamp ); - - if( fprintf( aFile, "$EndPCB_TARGET\n" ) != sizeof("$EndPCB_TARGET\n")-1 ) - goto out; - - rc = true; - -out: - return rc; -} - - - - /* Draw PCB_TARGET object: 2 segments + 1 circle * The circle radius is half the radius of the target * 2 lines have length the diameter of the target diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index 9715d74a4e..a8c8d750a1 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -292,396 +292,6 @@ void MODULE::DrawEdgesOnly( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& offs } -bool MODULE::Save( FILE* aFile ) const -{ - char statusTxt[8]; - BOARD_ITEM* item; - - bool rc = false; - - fprintf( aFile, "$MODULE %s\n", TO_UTF8( m_LibRef ) ); - - memset( statusTxt, 0, sizeof(statusTxt) ); - if( IsLocked() ) - statusTxt[0] = 'F'; - else - statusTxt[0] = '~'; - - if( m_ModuleStatus & MODULE_is_PLACED ) - statusTxt[1] = 'P'; - else - statusTxt[1] = '~'; - - fprintf( aFile, "Po %d %d %d %d %8.8lX %8.8lX %s\n", - m_Pos.x, m_Pos.y, - m_Orient, m_Layer, m_LastEdit_Time, - m_TimeStamp, statusTxt ); - - fprintf( aFile, "Li %s\n", TO_UTF8( m_LibRef ) ); - - if( !m_Doc.IsEmpty() ) - { - fprintf( aFile, "Cd %s\n", TO_UTF8( m_Doc ) ); - } - - if( !m_KeyWord.IsEmpty() ) - { - fprintf( aFile, "Kw %s\n", TO_UTF8( m_KeyWord ) ); - } - - fprintf( aFile, "Sc %8.8lX\n", m_TimeStamp ); - fprintf( aFile, "AR %s\n", TO_UTF8( m_Path ) ); - fprintf( aFile, "Op %X %X 0\n", m_CntRot90, m_CntRot180 ); - - if( m_LocalSolderMaskMargin != 0 ) - fprintf( aFile, ".SolderMask %d\n", m_LocalSolderMaskMargin ); - - if( m_LocalSolderPasteMargin != 0 ) - fprintf( aFile, ".SolderPaste %d\n", m_LocalSolderPasteMargin ); - - if( m_LocalSolderPasteMarginRatio != 0 ) - fprintf( aFile, ".SolderPasteRatio %g\n", m_LocalSolderPasteMarginRatio ); - - if( m_LocalClearance != 0 ) - fprintf( aFile, ".LocalClearance %d\n", m_LocalClearance ); - - // attributes - if( m_Attributs != MOD_DEFAULT ) - { - fprintf( aFile, "At " ); - - if( m_Attributs & MOD_CMS ) - fprintf( aFile, "SMD " ); - - if( m_Attributs & MOD_VIRTUAL ) - fprintf( aFile, "VIRTUAL " ); - - fprintf( aFile, "\n" ); - } - - // save reference - if( !m_Reference->Save( aFile ) ) - goto out; - - // save value - if( !m_Value->Save( aFile ) ) - goto out; - - // save drawing elements - for( item = m_Drawings; item; item = item->Next() ) - { - switch( item->Type() ) - { - case PCB_MODULE_TEXT_T: - case PCB_MODULE_EDGE_T: - if( !item->Save( aFile ) ) - goto out; - - break; - - default: -#if defined(DEBUG) - printf( "MODULE::Save() ignoring type %d\n", item->Type() ); -#endif - break; - } - } - - // save the pads - for( item = m_Pads; item; item = item->Next() ) - if( !item->Save( aFile ) ) - goto out; - - Write_3D_Descr( aFile ); - - fprintf( aFile, "$EndMODULE %s\n", TO_UTF8( m_LibRef ) ); - - rc = true; -out: - return rc; -} - - -/* Save the description of 3D MODULE - */ -int MODULE::Write_3D_Descr( FILE* File ) const -{ - char buf[512]; - - for( S3D_MASTER* t3D = m_3D_Drawings; t3D; t3D = t3D->Next() ) - { - if( !t3D->m_Shape3DName.IsEmpty() ) - { - fprintf( File, "$SHAPE3D\n" ); - - fprintf( File, "Na %s\n", EscapedUTF8( t3D->m_Shape3DName ).c_str() ); - - sprintf( buf, "Sc %lf %lf %lf\n", - t3D->m_MatScale.x, - t3D->m_MatScale.y, - t3D->m_MatScale.z ); - fprintf( File, "%s", to_point( buf ) ); - - sprintf( buf, "Of %lf %lf %lf\n", - t3D->m_MatPosition.x, - t3D->m_MatPosition.y, - t3D->m_MatPosition.z ); - fprintf( File, "%s", to_point( buf ) ); - - sprintf( buf, "Ro %lf %lf %lf\n", - t3D->m_MatRotation.x, - t3D->m_MatRotation.y, - t3D->m_MatRotation.z ); - fprintf( File, "%s", to_point( buf ) ); - - fprintf( File, "$EndSHAPE3D\n" ); - } - } - - return 0; -} - - -/* Read 3D module from file. (Ascii) - * The 1st line of descr ($MODULE) is assumed to be already read - * Returns 0 if OK - */ -int MODULE::Read_3D_Descr( LINE_READER* aReader ) -{ - char* Line = aReader->Line(); - char* text = Line + 3; - - S3D_MASTER* t3D = m_3D_Drawings; - - if( !t3D->m_Shape3DName.IsEmpty() ) - { - S3D_MASTER* n3D = new S3D_MASTER( this ); - - m_3D_Drawings.PushBack( n3D ); - - t3D = n3D; - } - - while( aReader->ReadLine() ) - { - Line = aReader->Line(); - - switch( Line[0] ) - { - case '$': - if( Line[1] == 'E' ) - return 0; - - return 1; - - case 'N': // Shape File Name - { - char buf[512]; - ReadDelimitedText( buf, text, 512 ); - t3D->m_Shape3DName = FROM_UTF8( buf ); - break; - } - - case 'S': // Scale - sscanf( text, "%lf %lf %lf\n", - &t3D->m_MatScale.x, - &t3D->m_MatScale.y, - &t3D->m_MatScale.z ); - break; - - case 'O': // Offset - sscanf( text, "%lf %lf %lf\n", - &t3D->m_MatPosition.x, - &t3D->m_MatPosition.y, - &t3D->m_MatPosition.z ); - break; - - case 'R': // Rotation - sscanf( text, "%lf %lf %lf\n", - &t3D->m_MatRotation.x, - &t3D->m_MatRotation.y, - &t3D->m_MatRotation.z ); - break; - - default: - break; - } - } - - return 1; -} - - -/* Read a MODULE description - * The first description line ($MODULE) is already read - * @return 0 if no error - */ -int MODULE::ReadDescr( LINE_READER* aReader ) -{ - char* Line; - char BufLine[256], BufCar1[128], * PtLine; - int itmp1, itmp2; - - while( aReader->ReadLine() ) - { - Line = aReader->Line(); - if( Line[0] == '$' ) - { - if( Line[1] == 'E' ) - break; - - if( Line[1] == 'P' ) - { - D_PAD* pad = new D_PAD( this ); - pad->ReadDescr( aReader ); - RotatePoint( &pad->m_Pos, m_Orient ); - pad->m_Pos.x += m_Pos.x; - pad->m_Pos.y += m_Pos.y; - - m_Pads.PushBack( pad ); - continue; - } - - if( Line[1] == 'S' ) - Read_3D_Descr( aReader ); - } - - if( strlen( Line ) < 4 ) - continue; - - PtLine = Line + 3; - - /* Decode the first code of the current line and read the - * corresponding data - */ - switch( Line[0] ) - { - case 'P': - memset( BufCar1, 0, sizeof(BufCar1) ); - sscanf( PtLine, "%d %d %d %d %lX %lX %s", - &m_Pos.x, &m_Pos.y, - &m_Orient, &m_Layer, - &m_LastEdit_Time, &m_TimeStamp, BufCar1 ); - - m_ModuleStatus = 0; - - if( BufCar1[0] == 'F' ) - SetLocked( true ); - - if( BufCar1[1] == 'P' ) - m_ModuleStatus |= MODULE_is_PLACED; - - break; - - case 'L': /* Li = read the library name of the footprint */ - *BufLine = 0; - sscanf( PtLine, " %s", BufLine ); - m_LibRef = FROM_UTF8( BufLine ); - break; - - case 'S': - sscanf( PtLine, " %lX", &m_TimeStamp ); - break; - - - case 'O': /* (Op)tions for auto placement */ - itmp1 = itmp2 = 0; - sscanf( PtLine, " %X %X", &itmp1, &itmp2 ); - - m_CntRot180 = itmp2 & 0x0F; - - if( m_CntRot180 > 10 ) - m_CntRot180 = 10; - - m_CntRot90 = itmp1 & 0x0F; - - if( m_CntRot90 > 10 ) - m_CntRot90 = 0; - - itmp1 = (itmp1 >> 4) & 0x0F; - - if( itmp1 > 10 ) - itmp1 = 0; - - m_CntRot90 |= itmp1 << 4; - break; - - case 'A': - if( Line[1] == 't' ) - { - /* At = (At)tributes of module */ - if( strstr( PtLine, "SMD" ) ) - m_Attributs |= MOD_CMS; - - if( strstr( PtLine, "VIRTUAL" ) ) - m_Attributs |= MOD_VIRTUAL; - } - - if( Line[1] == 'R' ) - { - // alternate reference, e.g. /478C2408/478AD1B6 - sscanf( PtLine, " %s", BufLine ); - m_Path = FROM_UTF8( BufLine ); - } - - break; - - case 'T': /* Read a footprint text description (ref, value, or - * drawing */ - TEXTE_MODULE * textm; - sscanf( Line + 1, "%d", &itmp1 ); - - if( itmp1 == TEXT_is_REFERENCE ) - textm = m_Reference; - else if( itmp1 == TEXT_is_VALUE ) - textm = m_Value; - else /* text is a drawing */ - { - textm = new TEXTE_MODULE( this ); - m_Drawings.PushBack( textm ); - } - textm->ReadDescr( aReader ); - break; - - case 'D': /* read a drawing item */ - EDGE_MODULE * edge; - edge = new EDGE_MODULE( this ); - m_Drawings.PushBack( edge ); - edge->ReadDescr( aReader ); - edge->SetDrawCoord(); - break; - - case 'C': /* read documentation data */ - m_Doc = FROM_UTF8( StrPurge( PtLine ) ); - break; - - case 'K': /* Read key words */ - m_KeyWord = FROM_UTF8( StrPurge( PtLine ) ); - break; - - case '.': /* Read specific data */ - if( strnicmp( Line, ".SolderMask ", 12 ) == 0 ) - m_LocalSolderMaskMargin = atoi( Line + 12 ); - else if( strnicmp( Line, ".SolderPaste ", 13 ) == 0 ) - m_LocalSolderPasteMargin = atoi( Line + 13 ); - else if( strnicmp( Line, ".SolderPasteRatio ", 18 ) == 0 ) - m_LocalSolderPasteMarginRatio = atof( Line + 18 ); - else if( strnicmp( Line, ".LocalClearance ", 16 ) == 0 ) - m_LocalClearance = atoi( Line + 16 ); - - break; - - default: - break; - } - } - - /* Recalculate the bounding box */ - CalculateBoundingBox(); - return 0; -} - - void MODULE::CalculateBoundingBox() { m_BoundaryBox = GetFootPrintRect(); @@ -1008,5 +618,4 @@ void MODULE::Show( int nestLevel, std::ostream& os ) << ">\n"; } - #endif diff --git a/pcbnew/class_netclass.cpp b/pcbnew/class_netclass.cpp index 061dff3c5f..a46536dc77 100644 --- a/pcbnew/class_netclass.cpp +++ b/pcbnew/class_netclass.cpp @@ -259,59 +259,6 @@ void BOARD::SynchronizeNetsAndNetClasses() } -bool NETCLASSES::Save( FILE* aFile ) const -{ - bool result; - - // save the default first. - result = m_Default.Save( aFile ); - - if( result ) - { - // the rest will be alphabetical in the *.brd file. - for( const_iterator i = begin(); i!=end(); ++i ) - { - NETCLASS* netclass = i->second; - - result = netclass->Save( aFile ); - if( !result ) - break; - } - } - - return result; -} - - -bool NETCLASS::Save( FILE* aFile ) const -{ - bool result = true; - - fprintf( aFile, "$NCLASS\n" ); - fprintf( aFile, "Name %s\n", EscapedUTF8( m_Name ).c_str() ); - fprintf( aFile, "Desc %s\n", EscapedUTF8( GetDescription() ).c_str() ); - - // Write parameters - - fprintf( aFile, "Clearance %d\n", GetClearance() ); - fprintf( aFile, "TrackWidth %d\n", GetTrackWidth() ); - - fprintf( aFile, "ViaDia %d\n", GetViaDiameter() ); - fprintf( aFile, "ViaDrill %d\n", GetViaDrill() ); - - fprintf( aFile, "uViaDia %d\n", GetuViaDiameter() ); - fprintf( aFile, "uViaDrill %d\n", GetuViaDrill() ); - - // Write members: - for( const_iterator i = begin(); i!=end(); ++i ) - fprintf( aFile, "AddNet %s\n", EscapedUTF8( *i ).c_str() ); - - fprintf( aFile, "$EndNCLASS\n" ); - - return result; -} - - #if defined(DEBUG) void NETCLASS::Show( int nestLevel, std::ostream& os ) @@ -333,80 +280,6 @@ void NETCLASS::Show( int nestLevel, std::ostream& os ) #endif -bool NETCLASS::ReadDescr( LINE_READER* aReader ) -{ - bool result = false; - char* line; - char buf[1024]; - wxString netname; - - while( aReader->ReadLine() ) - { - line = aReader->Line(); - if( strnicmp( line, "AddNet", 6 ) == 0 ) - { - ReadDelimitedText( buf, line + 6, sizeof(buf) ); - netname = FROM_UTF8( buf ); - Add( netname ); - continue; - } - - if( strnicmp( line, "$endNCLASS", sizeof( "$endNCLASS" ) - 1 ) == 0 ) - { - result = true; - break; - } - - if( strnicmp( line, "Clearance", 9 ) == 0 ) - { - SetClearance( atoi( line + 9 ) ); - continue; - } - if( strnicmp( line, "TrackWidth", 10 ) == 0 ) - { - SetTrackWidth( atoi( line + 10 ) ); - continue; - } - if( strnicmp( line, "ViaDia", 6 ) == 0 ) - { - SetViaDiameter( atoi( line + 6 ) ); - continue; - } - if( strnicmp( line, "ViaDrill", 8 ) == 0 ) - { - SetViaDrill( atoi( line + 8 ) ); - continue; - } - - if( strnicmp( line, "uViaDia", 7 ) == 0 ) - { - SetuViaDiameter( atoi( line + 7 ) ); - continue; - } - if( strnicmp( line, "uViaDrill", 9 ) == 0 ) - { - SetuViaDrill( atoi( line + 9 ) ); - continue; - } - - if( strnicmp( line, "Name", 4 ) == 0 ) - { - ReadDelimitedText( buf, line + 4, sizeof(buf) ); - m_Name = FROM_UTF8( buf ); - continue; - } - if( strnicmp( line, "Desc", 4 ) == 0 ) - { - ReadDelimitedText( buf, line + 4, sizeof(buf) ); - SetDescription( FROM_UTF8( buf ) ); - continue; - } - } - - return result; -} - - int NETCLASS::GetTrackMinWidth() const { return m_Parent->GetDesignSettings().m_TrackMinWidth; diff --git a/pcbnew/class_netinfo_item.cpp b/pcbnew/class_netinfo_item.cpp index ec0689de0d..2517e50fda 100644 --- a/pcbnew/class_netinfo_item.cpp +++ b/pcbnew/class_netinfo_item.cpp @@ -45,59 +45,6 @@ NETINFO_ITEM::~NETINFO_ITEM() } -/* Read NETINFO_ITEM from file. - * Returns 0 if OK - * 1 if incomplete reading - */ -int NETINFO_ITEM::ReadDescr( LINE_READER* aReader ) -{ - char* Line; - char Ltmp[1024]; - int tmp; - - while( aReader->ReadLine() ) - { - Line = aReader->Line(); - if( strnicmp( Line, "$End", 4 ) == 0 ) - return 0; - - if( strncmp( Line, "Na", 2 ) == 0 ) - { - sscanf( Line + 2, " %d", &tmp ); - SetNet( tmp ); - - ReadDelimitedText( Ltmp, Line + 2, sizeof(Ltmp) ); - m_Netname = FROM_UTF8( Ltmp ); - continue; - } - } - - return 1; -} - - -/** Note: the old name of class NETINFO_ITEM was EQUIPOT - * so in Save (and read) functions, for compatibility, we use EQUIPOT as - * keyword - */ -bool NETINFO_ITEM::Save( FILE* aFile ) const -{ - bool success = false; - - fprintf( aFile, "$EQUIPOT\n" ); - fprintf( aFile, "Na %d %s\n", GetNet(), EscapedUTF8( m_Netname ).c_str() ); - fprintf( aFile, "St %s\n", "~" ); - - if( fprintf( aFile, "$EndEQUIPOT\n" ) != sizeof("$EndEQUIPOT\n") - 1 ) - goto out; - - success = true; - -out: - return success; -} - - /** * Function SetNetname * @param aNetname : the new netname diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index 6fdbd4d3f4..c726e4029f 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -370,259 +370,6 @@ wxSize D_PAD::GetSolderPasteMargin() } -/* Read pad from file. - * The 1st line of descr ($PAD) is assumed to be already read - * Syntax: - * $PAD - * Sh "N1" C 550 550 0 0 1800 - * Dr 310 0 0 - * At STD N 00C0FFFF - * Do 3 "netname" - * Po 6000 -6000 - * $EndPAD - */ -int D_PAD::ReadDescr( LINE_READER* aReader ) -{ - char* Line; - char BufLine[1024], BufCar[256]; - char* PtLine; - int nn, ll, dx, dy; - - while( aReader->ReadLine() ) - { - Line = aReader->Line(); - - if( Line[0] == '$' ) - return 0; - - PtLine = Line + 3; - - /* Decode the first code and read the corresponding data - */ - switch( Line[0] ) - { - case 'S': // = Sh - /* Read pad name */ - nn = 0; - - while( (*PtLine != '"') && *PtLine ) - PtLine++; - - if( *PtLine ) - PtLine++; - - memset( m_Padname, 0, sizeof(m_Padname) ); - - while( (*PtLine != '"') && *PtLine ) - { - if( nn < (int) sizeof(m_Padname) ) - { - if( *PtLine > ' ' ) - { - m_Padname[nn] = *PtLine; nn++; - } - } - PtLine++; - } - - if( *PtLine == '"' ) - PtLine++; - - nn = sscanf( PtLine, " %s %d %d %d %d %d", - BufCar, &m_Size.x, &m_Size.y, - &m_DeltaSize.x, &m_DeltaSize.y, - &m_Orient ); - - ll = 0xFF & BufCar[0]; - - /* Read pad shape */ - m_PadShape = PAD_CIRCLE; - - switch( ll ) - { - case 'C': - m_PadShape = PAD_CIRCLE; break; - - case 'R': - m_PadShape = PAD_RECT; break; - - case 'O': - m_PadShape = PAD_OVAL; break; - - case 'T': - m_PadShape = PAD_TRAPEZOID; break; - } - - ComputeShapeMaxRadius(); - break; - - case 'D': - BufCar[0] = 0; - nn = sscanf( PtLine, "%d %d %d %s %d %d", &m_Drill.x, - &m_Offset.x, &m_Offset.y, BufCar, &dx, &dy ); - m_Drill.y = m_Drill.x; - m_DrillShape = PAD_CIRCLE; - - if( nn >= 6 ) // Drill shape = OVAL ? - { - if( BufCar[0] == 'O' ) - { - m_Drill.x = dx; m_Drill.y = dy; - m_DrillShape = PAD_OVAL; - } - } - - break; - - case 'A': - nn = sscanf( PtLine, "%s %s %X", BufLine, BufCar, - &m_layerMask ); - - /* BufCar is not used now update attributes */ - m_Attribut = PAD_STANDARD; - if( strncmp( BufLine, "SMD", 3 ) == 0 ) - m_Attribut = PAD_SMD; - - if( strncmp( BufLine, "CONN", 4 ) == 0 ) - m_Attribut = PAD_CONN; - - if( strncmp( BufLine, "HOLE", 4 ) == 0 ) - m_Attribut = PAD_HOLE_NOT_PLATED; - - break; - - case 'N': /* Read Netname */ - int netcode; - nn = sscanf( PtLine, "%d", &netcode ); - SetNet( netcode ); - - /* read Netname */ - ReadDelimitedText( BufLine, PtLine, sizeof(BufLine) ); - SetNetname( FROM_UTF8( StrPurge( BufLine ) ) ); - break; - - case 'P': - nn = sscanf( PtLine, "%d %d", &m_Pos0.x, &m_Pos0.y ); - m_Pos = m_Pos0; - break; - - case 'L': - int lengthdie; - nn = sscanf( PtLine, "%d", &lengthdie ); - m_LengthDie = lengthdie; - break; - - case '.': /* Read specific data */ - if( strnicmp( Line, ".SolderMask ", 12 ) == 0 ) - m_LocalSolderMaskMargin = atoi( Line + 12 ); - else if( strnicmp( Line, ".SolderPaste ", 13 ) == 0 ) - m_LocalSolderPasteMargin = atoi( Line + 13 ); - else if( strnicmp( Line, ".SolderPasteRatio ", 18 ) == 0 ) - m_LocalSolderPasteMarginRatio = atoi( Line + 18 ); - else if( strnicmp( Line, ".LocalClearance ", 16 ) == 0 ) - m_LocalClearance = atoi( Line + 16 ); - break; - - default: - DisplayError( NULL, wxT( "Err Pad: Id inconnu" ) ); - return 1; - } - } - - return 2; /* error : EOF */ -} - - -bool D_PAD::Save( FILE* aFile ) const -{ - int cshape; - const char* texttype; - - // check the return values for first and last fprints() in this function - if( fprintf( aFile, "$PAD\n" ) != sizeof("$PAD\n") - 1 ) - return false; - - switch( m_PadShape ) - { - case PAD_CIRCLE: - cshape = 'C'; break; - - case PAD_RECT: - cshape = 'R'; break; - - case PAD_OVAL: - cshape = 'O'; break; - - case PAD_TRAPEZOID: - cshape = 'T'; break; - - default: - cshape = 'C'; - DisplayError( NULL, _( "Unknown pad shape" ) ); - break; - } - - fprintf( aFile, "Sh \"%.4s\" %c %d %d %d %d %d\n", - m_Padname, cshape, m_Size.x, m_Size.y, - m_DeltaSize.x, m_DeltaSize.y, m_Orient ); - - fprintf( aFile, "Dr %d %d %d", m_Drill.x, m_Offset.x, m_Offset.y ); - - if( m_DrillShape == PAD_OVAL ) - { - fprintf( aFile, " %c %d %d", 'O', m_Drill.x, m_Drill.y ); - } - - fprintf( aFile, "\n" ); - - switch( m_Attribut ) - { - case PAD_STANDARD: - texttype = "STD"; break; - - case PAD_SMD: - texttype = "SMD"; break; - - case PAD_CONN: - texttype = "CONN"; break; - - case PAD_HOLE_NOT_PLATED: - texttype = "HOLE"; break; - - default: - texttype = "STD"; - DisplayError( NULL, wxT( "Invalid Pad attribute" ) ); - break; - } - - fprintf( aFile, "At %s N %8.8X\n", texttype, m_layerMask ); - - fprintf( aFile, "Ne %d %s\n", GetNet(), EscapedUTF8( m_Netname ).c_str() ); - - fprintf( aFile, "Po %d %d\n", m_Pos0.x, m_Pos0.y ); - - if( m_LengthDie != 0 ) - fprintf( aFile, "Le %d\n", m_LengthDie ); - - if( m_LocalSolderMaskMargin != 0 ) - fprintf( aFile, ".SolderMask %d\n", m_LocalSolderMaskMargin ); - - if( m_LocalSolderPasteMargin != 0 ) - fprintf( aFile, ".SolderPaste %d\n", m_LocalSolderPasteMargin ); - - if( m_LocalSolderPasteMarginRatio != 0 ) - fprintf( aFile, ".SolderPasteRatio %g\n", m_LocalSolderPasteMarginRatio ); - - if( m_LocalClearance != 0 ) - fprintf( aFile, ".LocalClearance %d\n", m_LocalClearance ); - - if( fprintf( aFile, "$EndPAD\n" ) != sizeof("$EndPAD\n") - 1 ) - return false; - - return true; -} - - void D_PAD::DisplayInfo( EDA_DRAW_FRAME* frame ) { MODULE* module; diff --git a/pcbnew/class_pcb_text.cpp b/pcbnew/class_pcb_text.cpp index 2605193d7e..51461da580 100644 --- a/pcbnew/class_pcb_text.cpp +++ b/pcbnew/class_pcb_text.cpp @@ -56,171 +56,6 @@ void TEXTE_PCB::Copy( TEXTE_PCB* source ) } -/** - * Function ReadTextePcbDescr - * Read a text description from pcb file. - * - * For a single line text: - * - * $TEXTPCB - * Te "Text example" - * Po 66750 53450 600 800 150 0 - * From 24 1 0 Italic - * $EndTEXTPCB - * - * For a multi line text - * - * $TEXTPCB - * Te "Text example" - * Nl "Line 2" - * Po 66750 53450 600 800 150 0 - * From 24 1 0 Italic - * $EndTEXTPCB - * Nl "line nn" is a line added to the current text - */ -int TEXTE_PCB::ReadTextePcbDescr( LINE_READER* aReader ) -{ - char* line; - char text[1024]; - char style[256]; - - while( aReader->ReadLine() ) - { - line = aReader->Line(); - if( strnicmp( line, "$EndTEXTPCB", 11 ) == 0 ) - return 0; - if( strncmp( line, "Te", 2 ) == 0 ) /* Text line (first line for multi line texts */ - { - ReadDelimitedText( text, line + 2, sizeof(text) ); - m_Text = FROM_UTF8( text ); - continue; - } - if( strncmp( line, "nl", 2 ) == 0 ) /* next line of the current text */ - { - ReadDelimitedText( text, line + 2, sizeof(text) ); - m_Text.Append( '\n' ); - m_Text += FROM_UTF8( text ); - continue; - } - if( strncmp( line, "Po", 2 ) == 0 ) - { - sscanf( line + 2, " %d %d %d %d %d %d", - &m_Pos.x, &m_Pos.y, &m_Size.x, &m_Size.y, - &m_Thickness, &m_Orient ); - - // Ensure the text has minimal size to see this text on screen: - if( m_Size.x < 5 ) - m_Size.x = 5; - if( m_Size.y < 5 ) - m_Size.y = 5; - continue; - } - if( strncmp( line, "De", 2 ) == 0 ) - { - style[0] = 0; - int normal_display = 1; - char hJustify = 'c'; - sscanf( line + 2, " %d %d %lX %s %c\n", &m_Layer, &normal_display, - &m_TimeStamp, style, &hJustify ); - - m_Mirror = normal_display ? false : true; - - if( m_Layer < FIRST_COPPER_LAYER ) - m_Layer = FIRST_COPPER_LAYER; - if( m_Layer > LAST_NO_COPPER_LAYER ) - m_Layer = LAST_NO_COPPER_LAYER; - - if( strnicmp( style, "Italic", 6 ) == 0 ) - m_Italic = 1; - else - m_Italic = 0; - - switch( hJustify ) - { - case 'l': - case 'L': - m_HJustify = GR_TEXT_HJUSTIFY_LEFT; - break; - case 'c': - case 'C': - m_HJustify = GR_TEXT_HJUSTIFY_CENTER; - break; - case 'r': - case 'R': - m_HJustify = GR_TEXT_HJUSTIFY_RIGHT; - break; - default: - m_HJustify = GR_TEXT_HJUSTIFY_CENTER; - break; - } - continue; - } - } - - // Set a reasonable width: - if( m_Thickness < 1 ) - m_Thickness = 1; - m_Thickness = Clamp_Text_PenSize( m_Thickness, m_Size ); - - return 1; -} - - -bool TEXTE_PCB::Save( FILE* aFile ) const -{ - if( m_Text.IsEmpty() ) - return true; - - if( fprintf( aFile, "$TEXTPCB\n" ) != sizeof("$TEXTPCB\n") - 1 ) - return false; - - const char* style = m_Italic ? "Italic" : "Normal"; - - wxArrayString* list = wxStringSplit( m_Text, '\n' ); - - for( unsigned ii = 0; ii < list->Count(); ii++ ) - { - wxString txt = list->Item( ii ); - - if ( ii == 0 ) - fprintf( aFile, "Te %s\n", EscapedUTF8( txt ).c_str() ); - else - fprintf( aFile, "nl %s\n", EscapedUTF8( txt ).c_str() ); - } - - delete list; - - fprintf( aFile, "Po %d %d %d %d %d %d\n", - m_Pos.x, m_Pos.y, m_Size.x, m_Size.y, m_Thickness, m_Orient ); - - char hJustify = 'L'; - switch( m_HJustify ) - { - case GR_TEXT_HJUSTIFY_LEFT: - hJustify = 'L'; - break; - case GR_TEXT_HJUSTIFY_CENTER: - hJustify = 'C'; - break; - case GR_TEXT_HJUSTIFY_RIGHT: - hJustify = 'R'; - break; - default: - hJustify = 'C'; - break; - } - - fprintf( aFile, "De %d %d %lX %s %c\n", m_Layer, - m_Mirror ? 0 : 1, - m_TimeStamp, style, hJustify ); - - if( fprintf( aFile, "$EndTEXTPCB\n" ) != sizeof("$EndTEXTPCB\n") - 1 ) - return false; - - return true; -} - - /* * Function Draw * Like tracks, texts are drawn in filled or sketch mode, never in line mode diff --git a/pcbnew/class_text_mod.cpp b/pcbnew/class_text_mod.cpp index 04da1db0cf..89e2df97ed 100644 --- a/pcbnew/class_text_mod.cpp +++ b/pcbnew/class_text_mod.cpp @@ -64,125 +64,6 @@ TEXTE_MODULE::~TEXTE_MODULE() } -/** - * Function Save - * writes the data structures for this object out to a FILE in "*.brd" format. - * @param aFile The FILE to write to. - * @return bool - true if success writing else false. - */ -bool TEXTE_MODULE::Save( FILE* aFile ) const -{ - MODULE* parent = (MODULE*) GetParent(); - int orient = m_Orient; - - // Due to the Pcbnew history, m_Orient is saved in screen value - // but it is handled as relative to its parent footprint - if( parent ) - orient += parent->m_Orient; - - int ret = fprintf( aFile, "T%d %d %d %d %d %d %d %c %c %d %c %s\n", - m_Type, - m_Pos0.x, m_Pos0.y, - m_Size.y, m_Size.x, - orient, - m_Thickness, - m_Mirror ? 'M' : 'N', m_NoShow ? 'I' : 'V', - GetLayer(), - m_Italic ? 'I' : 'N', - EscapedUTF8( m_Text ).c_str() - ); - - return ret > 20; -} - - -/** - * Function ReadDescr - * Read description from a given line in "*.brd" format. - * @param aReader The line reader object which contains the first line of description. - * @return int - > 0 if success reading else 0. - */ -int TEXTE_MODULE::ReadDescr( LINE_READER* aReader ) -{ - int success = true; - int type; - char BufCar1[128], BufCar2[128], BufCar3[128]; - char* line = aReader->Line(); - - int layer = SILKSCREEN_N_FRONT; - - BufCar1[0] = 0; - BufCar2[0] = 0; - BufCar3[0] = 0; - - if( sscanf( line + 1, "%d %d %d %d %d %d %d %s %s %d %s", - &type, - &m_Pos0.x, &m_Pos0.y, - &m_Size.y, &m_Size.x, - &m_Orient, &m_Thickness, - BufCar1, BufCar2, &layer, BufCar3 ) >= 10 ) - { - success = true; - } - - if( (type != TEXT_is_REFERENCE) && (type != TEXT_is_VALUE) ) - type = TEXT_is_DIVERS; - - m_Type = type; - - // Due to the Pcbnew history, .m_Orient is saved in screen value - // but it is handled as relative to its parent footprint - m_Orient -= ( (MODULE*) m_Parent )->m_Orient; - - if( BufCar1[0] == 'M' ) - m_Mirror = true; - else - m_Mirror = false; - - if( BufCar2[0] == 'I' ) - m_NoShow = true; - else - m_NoShow = false; - - if( BufCar3[0] == 'I' ) - m_Italic = true; - else - m_Italic = false; - - // Test for a reasonable layer: - if( layer < 0 ) - layer = 0; - if( layer > LAST_NO_COPPER_LAYER ) - layer = LAST_NO_COPPER_LAYER; - if( layer == LAYER_N_BACK ) - layer = SILKSCREEN_N_BACK; - else if( layer == LAYER_N_FRONT ) - layer = SILKSCREEN_N_FRONT; - - SetLayer( layer ); - - // Calculate the actual position. - SetDrawCoord(); - - - // Search and read the "text" string (a quoted text). - ReadDelimitedText( &m_Text, line ); - - // Test for a reasonable size: - if( m_Size.x < TEXTS_MIN_SIZE ) - m_Size.x = TEXTS_MIN_SIZE; - if( m_Size.y < TEXTS_MIN_SIZE ) - m_Size.y = TEXTS_MIN_SIZE; - - // Set a reasonable width: - if( m_Thickness < 1 ) - m_Thickness = 1; - m_Thickness = Clamp_Text_PenSize( m_Thickness, m_Size ); - - return success; -} - - void TEXTE_MODULE::Copy( TEXTE_MODULE* source ) { if( source == NULL ) diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp index 85deee363e..ac32d0b5bc 100644 --- a/pcbnew/class_track.cpp +++ b/pcbnew/class_track.cpp @@ -598,24 +598,6 @@ TRACK* TRACK::GetEndNetCode( int NetCode ) } -bool TRACK::Save( FILE* aFile ) const -{ - int type = 0; - - if( Type() == PCB_VIA_T ) - type = 1; - - fprintf( aFile, "Po %d %d %d %d %d %d %d\n", m_Shape, - m_Start.x, m_Start.y, m_End.x, m_End.y, m_Width, m_Drill ); - - fprintf( aFile, "De %d %d %d %lX %X\n", - m_Layer, type, GetNet(), - m_TimeStamp, ReturnStatus() ); - - return true; -} - - void TRACK::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int draw_mode, const wxPoint& aOffset ) { int l_trace; diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 5c426f95ee..8bbdcd0eb0 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -118,410 +118,6 @@ void ZONE_CONTAINER::SetNet( int aNetCode ) } -bool ZONE_CONTAINER::Save( FILE* aFile ) const -{ - unsigned item_pos; - int ret; - unsigned corners_count = m_Poly->corner.size(); - int outline_hatch; - char padoption; - - fprintf( aFile, "$CZONE_OUTLINE\n" ); - - // Save the outline main info - ret = fprintf( aFile, "ZInfo %8.8lX %d %s\n", - m_TimeStamp, m_NetCode, - EscapedUTF8( m_Netname ).c_str() ); - - if( ret < 3 ) - return false; - - // Save the outline layer info - ret = fprintf( aFile, "ZLayer %d\n", m_Layer ); - - if( ret < 1 ) - return false; - - // Save the outline aux info - switch( m_Poly->GetHatchStyle() ) - { - default: - case CPolyLine::NO_HATCH: - outline_hatch = 'N'; - break; - - case CPolyLine::DIAGONAL_EDGE: - outline_hatch = 'E'; - break; - - case CPolyLine::DIAGONAL_FULL: - outline_hatch = 'F'; - break; - } - - ret = fprintf( aFile, "ZAux %d %c\n", corners_count, outline_hatch ); - - if( ret < 2 ) - return false; - - // Save pad option and clearance - switch( m_PadOption ) - { - default: - case PAD_IN_ZONE: - padoption = 'I'; - break; - - case THERMAL_PAD: - padoption = 'T'; - break; - - case PAD_NOT_IN_ZONE: - padoption = 'X'; - break; - } - - ret = fprintf( aFile, "ZClearance %d %c\n", m_ZoneClearance, padoption ); - - if( ret < 2 ) - return false; - - ret = fprintf( aFile, "ZMinThickness %d\n", m_ZoneMinThickness ); - - if( ret < 1 ) - return false; - - ret = fprintf( aFile, - "ZOptions %d %d %c %d %d\n", - m_FillMode, - m_ArcToSegmentsCount, - m_IsFilled ? 'S' : 'F', - m_ThermalReliefGap, - m_ThermalReliefCopperBridge ); - - if( ret < 3 ) - return false; - - ret = fprintf( aFile, - "ZSmoothing %d %d\n", - cornerSmoothingType, cornerRadius ); - - if( ret < 2 ) - return false; - - // Save the corner list - for( item_pos = 0; item_pos < corners_count; item_pos++ ) - { - ret = fprintf( aFile, "ZCorner %d %d %d\n", - m_Poly->corner[item_pos].x, m_Poly->corner[item_pos].y, - m_Poly->corner[item_pos].end_contour ); - - if( ret < 3 ) - return false; - } - - // Save the PolysList - if( m_FilledPolysList.size() ) - { - fprintf( aFile, "$POLYSCORNERS\n" ); - - for( unsigned ii = 0; ii < m_FilledPolysList.size(); ii++ ) - { - const CPolyPt* corner = &m_FilledPolysList[ii]; - ret = fprintf( aFile, - "%d %d %d %d\n", - corner->x, - corner->y, - corner->end_contour, - corner->utility ); - - if( ret < 4 ) - return false; - } - - fprintf( aFile, "$endPOLYSCORNERS\n" ); - } - - // Save the filling segments list - if( m_FillSegmList.size() ) - { - fprintf( aFile, "$FILLSEGMENTS\n" ); - - for( unsigned ii = 0; ii < m_FillSegmList.size(); ii++ ) - { - ret = fprintf( aFile, "%d %d %d %d\n", - m_FillSegmList[ii].m_Start.x, m_FillSegmList[ii].m_Start.y, - m_FillSegmList[ii].m_End.x, m_FillSegmList[ii].m_End.y ); - - if( ret < 4 ) - return false; - } - - fprintf( aFile, "$endFILLSEGMENTS\n" ); - } - - fprintf( aFile, "$endCZONE_OUTLINE\n" ); - - return true; -} - - -int ZONE_CONTAINER::ReadDescr( LINE_READER* aReader ) -{ - char* Line, * text; - char netname_buffer[1024]; - int ret; - int outline_hatch = CPolyLine::NO_HATCH; - bool error = false, has_corner = false; - - netname_buffer[0] = 0; - - while( aReader->ReadLine() ) - { - Line = aReader->Line(); - - if( strnicmp( Line, "ZCorner", 7 ) == 0 ) // new corner found - { - int x; - int y; - int flag; - - text = Line + 7; - ret = sscanf( text, "%d %d %d", &x, &y, &flag ); - - if( ret < 3 ) - { - error = true; - } - else - { - if( !has_corner ) - m_Poly->Start( m_Layer, x, y, outline_hatch ); - else - AppendCorner( wxPoint( x, y ) ); - - has_corner = true; - - if( flag ) - m_Poly->Close(); - } - } - else if( strnicmp( Line, "ZInfo", 5 ) == 0 ) // general info found - { - int ts; - int netcode; - - text = Line + 5; - ret = sscanf( text, "%X %d %s", &ts, &netcode, netname_buffer ); - - if( ret < 3 ) - { - error = true; - } - else - { - m_TimeStamp = ts; - m_NetCode = netcode; - ReadDelimitedText( netname_buffer, netname_buffer, 1024 ); - m_Netname = FROM_UTF8( netname_buffer ); - } - } - else if( strnicmp( Line, "ZLayer", 6 ) == 0 ) // layer found - { - int x; - - text = Line + 6; - ret = sscanf( text, "%d", &x ); - - if( ret < 1 ) - error = true; - else - m_Layer = x; - } - else if( strnicmp( Line, "ZAux", 4 ) == 0 ) // aux info found - { - int x; - char hopt[10]; - - text = Line + 4; - ret = sscanf( text, "%d %c", &x, hopt ); - - if( ret < 2 ) - { - error = true; - } - else - { - switch( hopt[0] ) - { - case 'n': - case 'N': - outline_hatch = CPolyLine::NO_HATCH; - break; - - case 'e': - case 'E': - outline_hatch = CPolyLine::DIAGONAL_EDGE; - break; - - case 'f': - case 'F': - outline_hatch = CPolyLine::DIAGONAL_FULL; - break; - } - } - /* Set hatch mode later, after reading outlines corners data */ - } - else if( strnicmp( Line, "ZSmoothing", 10 ) == 0 ) - { - int tempSmoothingType; - int tempCornerRadius; - text = Line + 10; - ret = sscanf( text, "%d %d", &tempSmoothingType, &tempCornerRadius ); - - if( ret < 2 ) - return false; - - if( tempSmoothingType >= ZONE_SETTING::SMOOTHING_LAST) - return false; - - if( tempSmoothingType < 0 ) - return false; - - cornerSmoothingType = tempSmoothingType; - SetCornerRadius( tempCornerRadius ); - } - else if( strnicmp( Line, "ZOptions", 8 ) == 0 ) // Options info found - { - int fillmode = 1; - int arcsegmentcount = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF; - char fillstate = 'F'; - text = Line + 8; - ret = sscanf( text, "%d %d %c %d %d", &fillmode, &arcsegmentcount, &fillstate, - &m_ThermalReliefGap, &m_ThermalReliefCopperBridge ); - - if( ret < 1 ) // Must find 1 or more args. - return false; - else - m_FillMode = fillmode ? 1 : 0; - - if( arcsegmentcount >= ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF ) - m_ArcToSegmentsCount = ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF; - - m_IsFilled = (fillstate == 'S') ? true : false; - } - else if( strnicmp( Line, "ZClearance", 10 ) == 0 ) // Clearance and pad options info found - { - int clearance = 200; - char padoption; - text = Line + 10; - ret = sscanf( text, "%d %1c", &clearance, &padoption ); - - if( ret < 2 ) - { - error = true; - } - else - { - m_ZoneClearance = clearance; - - switch( padoption ) - { - case 'i': - case 'I': - m_PadOption = PAD_IN_ZONE; - break; - - case 't': - case 'T': - m_PadOption = THERMAL_PAD; - break; - - case 'x': - case 'X': - m_PadOption = PAD_NOT_IN_ZONE; - break; - } - } - } - else if( strnicmp( Line, "ZMinThickness", 13 ) == 0 ) // Min Thickness info found - { - int thickness; - text = Line + 13; - ret = sscanf( text, "%d", &thickness ); - - if( ret < 1 ) - error = true; - else - m_ZoneMinThickness = thickness; - } - else if( strnicmp( Line, "$POLYSCORNERS", 13 ) == 0 ) // Read the PolysList (polygons used for fill areas in the zone) - { - while( aReader->ReadLine() ) - { - Line = aReader->Line(); - - if( strnicmp( Line, "$endPOLYSCORNERS", 4 ) == 0 ) - break; - - CPolyPt corner; - int end_contour, utility; - utility = 0; - ret = sscanf( Line, - "%d %d %d %d", - &corner.x, - &corner.y, - &end_contour, - &utility ); - if( ret < 4 ) - return false; - - corner.end_contour = end_contour ? true : false; - corner.utility = utility; - m_FilledPolysList.push_back( corner ); - } - } - else if( strnicmp( Line, "$FILLSEGMENTS", 13 ) == 0 ) - { - SEGMENT segm; - while( aReader->ReadLine() ) - { - Line = aReader->Line(); - - if( strnicmp( Line, "$endFILLSEGMENTS", 4 ) == 0 ) - break; - - ret = sscanf( Line, - "%d %d %d %d", - &segm.m_Start.x, - &segm.m_Start.y, - &segm.m_End.x, - &segm.m_End.y ); - if( ret < 4 ) - return false; - - m_FillSegmList.push_back( segm ); - } - } - else if( strnicmp( Line, "$end", 4 ) == 0 ) // end of description - { - break; - } - } - - if( !IsOnCopperLayer() ) - { - m_FillMode = 0; - SetNet( 0 ); - } - - /* Set hatch here, when outlines corners are read */ - m_Poly->SetHatch( outline_hatch ); - - return error ? 0 : 1; -} - - void ZONE_CONTAINER::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int aDrawMode, const wxPoint& offset ) { if( DC == NULL ) diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp index 25578613c2..2768c616a3 100644 --- a/pcbnew/files.cpp +++ b/pcbnew/files.cpp @@ -200,7 +200,7 @@ the changes?" ) ) ) GetScreen()->SetFileName( fileName.GetFullPath() ); -#if 1 +#if !defined(USE_NEW_PCBNEW_LOAD) // Start read PCB file FILE* source = wxFopen( GetScreen()->GetFileName(), wxT( "rt" ) ); diff --git a/pcbnew/ioascii.cpp b/pcbnew/ioascii.cpp index be17ec50c8..87d6c3b0bd 100644 --- a/pcbnew/ioascii.cpp +++ b/pcbnew/ioascii.cpp @@ -963,6 +963,8 @@ static bool ReadSheetDescr( BASE_SCREEN* screen, LINE_READER* aReader ) } +#if !defined( USE_NEW_PCBNEW_LOAD ) + int PCB_EDIT_FRAME::ReadPcbFile( LINE_READER* aReader, bool Append ) { wxBusyCursor dummy; @@ -1140,6 +1142,8 @@ int PCB_EDIT_FRAME::ReadPcbFile( LINE_READER* aReader, bool Append ) return 1; } +#endif + #ifdef PCBNEW @@ -1188,5 +1192,4 @@ int PCB_EDIT_FRAME::SavePcbFormatAscii( FILE* aFile ) return rc; } - #endif diff --git a/pcbnew/item_io.cpp b/pcbnew/item_io.cpp new file mode 100644 index 0000000000..560e35c683 --- /dev/null +++ b/pcbnew/item_io.cpp @@ -0,0 +1,2213 @@ + + /** + * @file item_io.cpp + * @brief Routines for reading and saving of structures in ASCII file common to Pcbnew and CvPcb. + * This is migrationary and temporary while we move the IO_MGR. + */ + +#include "fctsys.h" +#include "confirm.h" +#include "kicad_string.h" +#include "build_version.h" +#include "wxPcbStruct.h" +#include "richio.h" +#include "macros.h" +#include "pcbcommon.h" + +#ifdef PCBNEW +/** + * @todo Fix having to recompile the same file with a different defintion. This is + * what C++ derivation was designed to solve. + */ +//#include "zones.h" +#endif + +#include "zones.h" + +#ifdef CVPCB +#include "cvpcb.h" +#endif + +#include "config.h" +#include "class_board.h" +#include "class_module.h" +#include "class_track.h" +#include "class_pcb_text.h" +#include "class_zone.h" +#include "class_dimension.h" +#include "class_drawsegment.h" +#include "class_mire.h" + +#include "pcbnew.h" +#include "pcbnew_id.h" +#include "autorout.h" +#include "pcb_plot_params.h" + +#include "3d_struct.h" +#include "trigo.h" +#include "class_edge_mod.h" +#include "pcbnew.h" +#include "drawtxt.h" + +#define MAX_WIDTH 10000 /* Thickness (in 1 / 10000 ") of maximum reasonable features, text... */ + + +#if !defined(USE_NEW_PCBNEW_SAVE) + +bool BOARD::Save( FILE* aFile ) const +{ + bool rc = false; + BOARD_ITEM* item; + + // save the nets + for( unsigned ii = 0; ii < m_NetInfo->GetCount(); ii++ ) + if( !m_NetInfo->GetNetItem( ii )->Save( aFile ) ) + goto out; + + // Saved nets do not include netclass names, so save netclasses after nets. + m_NetClasses.Save( aFile ); + + // save the modules + for( item = m_Modules; item; item = item->Next() ) + if( !item->Save( aFile ) ) + goto out; + + for( item = m_Drawings; item; item = item->Next() ) + { + switch( item->Type() ) + { + case PCB_TEXT_T: + case PCB_LINE_T: + case PCB_TARGET_T: + case PCB_DIMENSION_T: + if( !item->Save( aFile ) ) + goto out; + + break; + + default: + + // future: throw exception here +#if defined(DEBUG) + printf( "BOARD::Save() ignoring m_Drawings type %d\n", item->Type() ); +#endif + break; + } + } + + // do not save MARKER_PCBs, they can be regenerated easily + + // save the tracks & vias + fprintf( aFile, "$TRACK\n" ); + + for( item = m_Track; item; item = item->Next() ) + { + if( !item->Save( aFile ) ) + goto out; + } + + fprintf( aFile, "$EndTRACK\n" ); + + // save the zones + fprintf( aFile, "$ZONE\n" ); + + for( item = m_Zone; item; item = item->Next() ) + { + if( !item->Save( aFile ) ) + goto out; + } + + fprintf( aFile, "$EndZONE\n" ); + + // save the zone edges + for( unsigned ii = 0; ii < m_ZoneDescriptorList.size(); ii++ ) + { + ZONE_CONTAINER* edge_zone = m_ZoneDescriptorList[ii]; + edge_zone->Save( aFile ); + } + + + if( fprintf( aFile, "$EndBOARD\n" ) != sizeof("$EndBOARD\n") - 1 ) + goto out; + + rc = true; // wrote all OK + +out: + return rc; +} + + +bool DRAWSEGMENT::Save( FILE* aFile ) const +{ + if( fprintf( aFile, "$DRAWSEGMENT\n" ) != sizeof("$DRAWSEGMENT\n") - 1 ) + return false; + + fprintf( aFile, "Po %d %d %d %d %d %d\n", + m_Shape, + m_Start.x, m_Start.y, + m_End.x, m_End.y, m_Width ); + + if( m_Type != S_CURVE ) + { + fprintf( aFile, "De %d %d %d %lX %X\n", + m_Layer, m_Type, m_Angle, + m_TimeStamp, ReturnStatus() ); + } + else + { + fprintf( aFile, "De %d %d %d %lX %X %d %d %d %d\n", + m_Layer, m_Type, m_Angle, + m_TimeStamp, ReturnStatus(), + m_BezierC1.x,m_BezierC1.y, + m_BezierC2.x,m_BezierC2.y); + } + + if( fprintf( aFile, "$EndDRAWSEGMENT\n" ) != sizeof("$EndDRAWSEGMENT\n") - 1 ) + return false; + + return true; +} + + +/** Note: the old name of class NETINFO_ITEM was EQUIPOT + * so in Save (and read) functions, for compatibility, we use EQUIPOT as + * keyword + */ +bool NETINFO_ITEM::Save( FILE* aFile ) const +{ + bool success = false; + + fprintf( aFile, "$EQUIPOT\n" ); + fprintf( aFile, "Na %d %s\n", GetNet(), EscapedUTF8( m_Netname ).c_str() ); + fprintf( aFile, "St %s\n", "~" ); + + if( fprintf( aFile, "$EndEQUIPOT\n" ) != sizeof("$EndEQUIPOT\n") - 1 ) + goto out; + + success = true; + +out: + return success; +} + + +bool PCB_TARGET::Save( FILE* aFile ) const +{ + bool rc = false; + + if( fprintf( aFile, "$PCB_TARGET\n" ) != sizeof("$PCB_TARGET\n")-1 ) + goto out; + + fprintf( aFile, "Po %X %d %d %d %d %d %8.8lX\n", + m_Shape, m_Layer, + m_Pos.x, m_Pos.y, + m_Size, m_Width, m_TimeStamp ); + + if( fprintf( aFile, "$EndPCB_TARGET\n" ) != sizeof("$EndPCB_TARGET\n")-1 ) + goto out; + + rc = true; + +out: + return rc; +} + + +bool ZONE_CONTAINER::Save( FILE* aFile ) const +{ + unsigned item_pos; + int ret; + unsigned corners_count = m_Poly->corner.size(); + int outline_hatch; + char padoption; + + fprintf( aFile, "$CZONE_OUTLINE\n" ); + + // Save the outline main info + ret = fprintf( aFile, "ZInfo %8.8lX %d %s\n", + m_TimeStamp, m_NetCode, + EscapedUTF8( m_Netname ).c_str() ); + + if( ret < 3 ) + return false; + + // Save the outline layer info + ret = fprintf( aFile, "ZLayer %d\n", m_Layer ); + + if( ret < 1 ) + return false; + + // Save the outline aux info + switch( m_Poly->GetHatchStyle() ) + { + default: + case CPolyLine::NO_HATCH: + outline_hatch = 'N'; + break; + + case CPolyLine::DIAGONAL_EDGE: + outline_hatch = 'E'; + break; + + case CPolyLine::DIAGONAL_FULL: + outline_hatch = 'F'; + break; + } + + ret = fprintf( aFile, "ZAux %d %c\n", corners_count, outline_hatch ); + + if( ret < 2 ) + return false; + + // Save pad option and clearance + switch( m_PadOption ) + { + default: + case PAD_IN_ZONE: + padoption = 'I'; + break; + + case THERMAL_PAD: + padoption = 'T'; + break; + + case PAD_NOT_IN_ZONE: + padoption = 'X'; + break; + } + + ret = fprintf( aFile, "ZClearance %d %c\n", m_ZoneClearance, padoption ); + + if( ret < 2 ) + return false; + + ret = fprintf( aFile, "ZMinThickness %d\n", m_ZoneMinThickness ); + + if( ret < 1 ) + return false; + + ret = fprintf( aFile, + "ZOptions %d %d %c %d %d\n", + m_FillMode, + m_ArcToSegmentsCount, + m_IsFilled ? 'S' : 'F', + m_ThermalReliefGap, + m_ThermalReliefCopperBridge ); + + if( ret < 3 ) + return false; + + ret = fprintf( aFile, + "ZSmoothing %d %d\n", + cornerSmoothingType, cornerRadius ); + + if( ret < 2 ) + return false; + + // Save the corner list + for( item_pos = 0; item_pos < corners_count; item_pos++ ) + { + ret = fprintf( aFile, "ZCorner %d %d %d\n", + m_Poly->corner[item_pos].x, m_Poly->corner[item_pos].y, + m_Poly->corner[item_pos].end_contour ); + + if( ret < 3 ) + return false; + } + + // Save the PolysList + if( m_FilledPolysList.size() ) + { + fprintf( aFile, "$POLYSCORNERS\n" ); + + for( unsigned ii = 0; ii < m_FilledPolysList.size(); ii++ ) + { + const CPolyPt* corner = &m_FilledPolysList[ii]; + ret = fprintf( aFile, + "%d %d %d %d\n", + corner->x, + corner->y, + corner->end_contour, + corner->utility ); + + if( ret < 4 ) + return false; + } + + fprintf( aFile, "$endPOLYSCORNERS\n" ); + } + + // Save the filling segments list + if( m_FillSegmList.size() ) + { + fprintf( aFile, "$FILLSEGMENTS\n" ); + + for( unsigned ii = 0; ii < m_FillSegmList.size(); ii++ ) + { + ret = fprintf( aFile, "%d %d %d %d\n", + m_FillSegmList[ii].m_Start.x, m_FillSegmList[ii].m_Start.y, + m_FillSegmList[ii].m_End.x, m_FillSegmList[ii].m_End.y ); + + if( ret < 4 ) + return false; + } + + fprintf( aFile, "$endFILLSEGMENTS\n" ); + } + + fprintf( aFile, "$endCZONE_OUTLINE\n" ); + + return true; +} + + +bool NETCLASSES::Save( FILE* aFile ) const +{ + bool result; + + // save the default first. + result = m_Default.Save( aFile ); + + if( result ) + { + // the rest will be alphabetical in the *.brd file. + for( const_iterator i = begin(); i!=end(); ++i ) + { + NETCLASS* netclass = i->second; + + result = netclass->Save( aFile ); + if( !result ) + break; + } + } + + return result; +} + + +bool NETCLASS::Save( FILE* aFile ) const +{ + bool result = true; + + fprintf( aFile, "$NCLASS\n" ); + fprintf( aFile, "Name %s\n", EscapedUTF8( m_Name ).c_str() ); + fprintf( aFile, "Desc %s\n", EscapedUTF8( GetDescription() ).c_str() ); + + // Write parameters + + fprintf( aFile, "Clearance %d\n", GetClearance() ); + fprintf( aFile, "TrackWidth %d\n", GetTrackWidth() ); + + fprintf( aFile, "ViaDia %d\n", GetViaDiameter() ); + fprintf( aFile, "ViaDrill %d\n", GetViaDrill() ); + + fprintf( aFile, "uViaDia %d\n", GetuViaDiameter() ); + fprintf( aFile, "uViaDrill %d\n", GetuViaDrill() ); + + // Write members: + for( const_iterator i = begin(); i!=end(); ++i ) + fprintf( aFile, "AddNet %s\n", EscapedUTF8( *i ).c_str() ); + + fprintf( aFile, "$EndNCLASS\n" ); + + return result; +} + + +bool TEXTE_PCB::Save( FILE* aFile ) const +{ + if( m_Text.IsEmpty() ) + return true; + + if( fprintf( aFile, "$TEXTPCB\n" ) != sizeof("$TEXTPCB\n") - 1 ) + return false; + + const char* style = m_Italic ? "Italic" : "Normal"; + + wxArrayString* list = wxStringSplit( m_Text, '\n' ); + + for( unsigned ii = 0; ii < list->Count(); ii++ ) + { + wxString txt = list->Item( ii ); + + if ( ii == 0 ) + fprintf( aFile, "Te %s\n", EscapedUTF8( txt ).c_str() ); + else + fprintf( aFile, "nl %s\n", EscapedUTF8( txt ).c_str() ); + } + + delete list; + + fprintf( aFile, "Po %d %d %d %d %d %d\n", + m_Pos.x, m_Pos.y, m_Size.x, m_Size.y, m_Thickness, m_Orient ); + + char hJustify = 'L'; + switch( m_HJustify ) + { + case GR_TEXT_HJUSTIFY_LEFT: + hJustify = 'L'; + break; + case GR_TEXT_HJUSTIFY_CENTER: + hJustify = 'C'; + break; + case GR_TEXT_HJUSTIFY_RIGHT: + hJustify = 'R'; + break; + default: + hJustify = 'C'; + break; + } + + fprintf( aFile, "De %d %d %lX %s %c\n", m_Layer, + m_Mirror ? 0 : 1, + m_TimeStamp, style, hJustify ); + + if( fprintf( aFile, "$EndTEXTPCB\n" ) != sizeof("$EndTEXTPCB\n") - 1 ) + return false; + + return true; +} + + +/** + * Function Save + * writes the data structures for this object out to a FILE in "*.brd" format. + * @param aFile The FILE to write to. + * @return bool - true if success writing else false. + */ +bool TEXTE_MODULE::Save( FILE* aFile ) const +{ + MODULE* parent = (MODULE*) GetParent(); + int orient = m_Orient; + + // Due to the Pcbnew history, m_Orient is saved in screen value + // but it is handled as relative to its parent footprint + if( parent ) + orient += parent->m_Orient; + + int ret = fprintf( aFile, "T%d %d %d %d %d %d %d %c %c %d %c %s\n", + m_Type, + m_Pos0.x, m_Pos0.y, + m_Size.y, m_Size.x, + orient, + m_Thickness, + m_Mirror ? 'M' : 'N', m_NoShow ? 'I' : 'V', + GetLayer(), + m_Italic ? 'I' : 'N', + EscapedUTF8( m_Text ).c_str() + ); + + return ret > 20; +} + + +bool EDGE_MODULE::Save( FILE* aFile ) const +{ + int ret = -1; + + switch( m_Shape ) + { + case S_SEGMENT: + ret = fprintf( aFile, "DS %d %d %d %d %d %d\n", + m_Start0.x, m_Start0.y, + m_End0.x, m_End0.y, + m_Width, m_Layer ); + break; + + case S_CIRCLE: + ret = fprintf( aFile, "DC %d %d %d %d %d %d\n", + m_Start0.x, m_Start0.y, + m_End0.x, m_End0.y, + m_Width, m_Layer ); + break; + + case S_ARC: + ret = fprintf( aFile, "DA %d %d %d %d %d %d %d\n", + m_Start0.x, m_Start0.y, + m_End0.x, m_End0.y, + m_Angle, + m_Width, m_Layer ); + break; + + case S_POLYGON: + ret = fprintf( aFile, "DP %d %d %d %d %d %d %d\n", + m_Start0.x, m_Start0.y, + m_End0.x, m_End0.y, + (int) m_PolyPoints.size(), + m_Width, m_Layer ); + + for( unsigned i = 0; i 5; +} + + +bool TRACK::Save( FILE* aFile ) const +{ + int type = 0; + + if( Type() == PCB_VIA_T ) + type = 1; + + fprintf( aFile, "Po %d %d %d %d %d %d %d\n", m_Shape, + m_Start.x, m_Start.y, m_End.x, m_End.y, m_Width, m_Drill ); + + fprintf( aFile, "De %d %d %d %lX %X\n", + m_Layer, type, GetNet(), + m_TimeStamp, ReturnStatus() ); + + return true; +} + + +bool DIMENSION::Save( FILE* aFile ) const +{ + bool rc = false; + + // note: COTATION was the previous name of DIMENSION + // this old keyword is used here for compatibility + const char keyWordLine[] = "$COTATION\n"; + const char keyWordLineEnd[] = "$endCOTATION\n"; + + if( fputs( keyWordLine, aFile ) == EOF ) + goto out; + + fprintf( aFile, "Ge %d %d %lX\n", m_Shape, m_Layer, m_TimeStamp ); + + fprintf( aFile, "Va %d\n", m_Value ); + + if( !m_Text->m_Text.IsEmpty() ) + fprintf( aFile, "Te %s\n", EscapedUTF8( m_Text->m_Text ).c_str() ); + else + fprintf( aFile, "Te \"?\"\n" ); + + fprintf( aFile, "Po %d %d %d %d %d %d %d\n", + m_Text->m_Pos.x, m_Text->m_Pos.y, + m_Text->m_Size.x, m_Text->m_Size.y, + m_Text->GetThickness(), m_Text->GetOrientation(), + m_Text->m_Mirror ? 0 : 1 ); + + fprintf( aFile, "Sb %d %d %d %d %d %d\n", S_SEGMENT, + m_crossBarOx, m_crossBarOy, + m_crossBarFx, m_crossBarFy, m_Width ); + + fprintf( aFile, "Sd %d %d %d %d %d %d\n", S_SEGMENT, + m_featureLineDOx, m_featureLineDOy, + m_featureLineDFx, m_featureLineDFy, m_Width ); + + fprintf( aFile, "Sg %d %d %d %d %d %d\n", S_SEGMENT, + m_featureLineGOx, m_featureLineGOy, + m_featureLineGFx, m_featureLineGFy, m_Width ); + + fprintf( aFile, "S1 %d %d %d %d %d %d\n", S_SEGMENT, + m_arrowD1Ox, m_arrowD1Oy, + m_arrowD1Fx, m_arrowD1Fy, m_Width ); + + fprintf( aFile, "S2 %d %d %d %d %d %d\n", S_SEGMENT, + m_arrowD2Ox, m_arrowD2Oy, + m_arrowD2Fx, m_arrowD2Fy, m_Width ); + + + fprintf( aFile, "S3 %d %d %d %d %d %d\n", S_SEGMENT, + m_arrowG1Ox, m_arrowG1Oy, + m_arrowG1Fx, m_arrowG1Fy, m_Width ); + + fprintf( aFile, "S4 %d %d %d %d %d %d\n", S_SEGMENT, + m_arrowG2Ox, m_arrowG2Oy, + m_arrowG2Fx, m_arrowG2Fy, m_Width ); + + if( fputs( keyWordLineEnd, aFile ) == EOF ) + goto out; + + rc = true; + +out: + return rc; +} + + +bool D_PAD::Save( FILE* aFile ) const +{ + int cshape; + const char* texttype; + + // check the return values for first and last fprints() in this function + if( fprintf( aFile, "$PAD\n" ) != sizeof("$PAD\n") - 1 ) + return false; + + switch( m_PadShape ) + { + case PAD_CIRCLE: + cshape = 'C'; break; + + case PAD_RECT: + cshape = 'R'; break; + + case PAD_OVAL: + cshape = 'O'; break; + + case PAD_TRAPEZOID: + cshape = 'T'; break; + + default: + cshape = 'C'; + DisplayError( NULL, _( "Unknown pad shape" ) ); + break; + } + + fprintf( aFile, "Sh \"%.4s\" %c %d %d %d %d %d\n", + m_Padname, cshape, m_Size.x, m_Size.y, + m_DeltaSize.x, m_DeltaSize.y, m_Orient ); + + fprintf( aFile, "Dr %d %d %d", m_Drill.x, m_Offset.x, m_Offset.y ); + + if( m_DrillShape == PAD_OVAL ) + { + fprintf( aFile, " %c %d %d", 'O', m_Drill.x, m_Drill.y ); + } + + fprintf( aFile, "\n" ); + + switch( m_Attribut ) + { + case PAD_STANDARD: + texttype = "STD"; break; + + case PAD_SMD: + texttype = "SMD"; break; + + case PAD_CONN: + texttype = "CONN"; break; + + case PAD_HOLE_NOT_PLATED: + texttype = "HOLE"; break; + + default: + texttype = "STD"; + DisplayError( NULL, wxT( "Invalid Pad attribute" ) ); + break; + } + + fprintf( aFile, "At %s N %8.8X\n", texttype, m_layerMask ); + + fprintf( aFile, "Ne %d %s\n", GetNet(), EscapedUTF8( m_Netname ).c_str() ); + + fprintf( aFile, "Po %d %d\n", m_Pos0.x, m_Pos0.y ); + + if( m_LengthDie != 0 ) + fprintf( aFile, "Le %d\n", m_LengthDie ); + + if( m_LocalSolderMaskMargin != 0 ) + fprintf( aFile, ".SolderMask %d\n", m_LocalSolderMaskMargin ); + + if( m_LocalSolderPasteMargin != 0 ) + fprintf( aFile, ".SolderPaste %d\n", m_LocalSolderPasteMargin ); + + if( m_LocalSolderPasteMarginRatio != 0 ) + fprintf( aFile, ".SolderPasteRatio %g\n", m_LocalSolderPasteMarginRatio ); + + if( m_LocalClearance != 0 ) + fprintf( aFile, ".LocalClearance %d\n", m_LocalClearance ); + + if( fprintf( aFile, "$EndPAD\n" ) != sizeof("$EndPAD\n") - 1 ) + return false; + + return true; +} + + +bool MODULE::Save( FILE* aFile ) const +{ + char statusTxt[8]; + BOARD_ITEM* item; + + bool rc = false; + + fprintf( aFile, "$MODULE %s\n", TO_UTF8( m_LibRef ) ); + + memset( statusTxt, 0, sizeof(statusTxt) ); + if( IsLocked() ) + statusTxt[0] = 'F'; + else + statusTxt[0] = '~'; + + if( m_ModuleStatus & MODULE_is_PLACED ) + statusTxt[1] = 'P'; + else + statusTxt[1] = '~'; + + fprintf( aFile, "Po %d %d %d %d %8.8lX %8.8lX %s\n", + m_Pos.x, m_Pos.y, + m_Orient, m_Layer, m_LastEdit_Time, + m_TimeStamp, statusTxt ); + + fprintf( aFile, "Li %s\n", TO_UTF8( m_LibRef ) ); + + if( !m_Doc.IsEmpty() ) + { + fprintf( aFile, "Cd %s\n", TO_UTF8( m_Doc ) ); + } + + if( !m_KeyWord.IsEmpty() ) + { + fprintf( aFile, "Kw %s\n", TO_UTF8( m_KeyWord ) ); + } + + fprintf( aFile, "Sc %8.8lX\n", m_TimeStamp ); + fprintf( aFile, "AR %s\n", TO_UTF8( m_Path ) ); + fprintf( aFile, "Op %X %X 0\n", m_CntRot90, m_CntRot180 ); + + if( m_LocalSolderMaskMargin != 0 ) + fprintf( aFile, ".SolderMask %d\n", m_LocalSolderMaskMargin ); + + if( m_LocalSolderPasteMargin != 0 ) + fprintf( aFile, ".SolderPaste %d\n", m_LocalSolderPasteMargin ); + + if( m_LocalSolderPasteMarginRatio != 0 ) + fprintf( aFile, ".SolderPasteRatio %g\n", m_LocalSolderPasteMarginRatio ); + + if( m_LocalClearance != 0 ) + fprintf( aFile, ".LocalClearance %d\n", m_LocalClearance ); + + // attributes + if( m_Attributs != MOD_DEFAULT ) + { + fprintf( aFile, "At " ); + + if( m_Attributs & MOD_CMS ) + fprintf( aFile, "SMD " ); + + if( m_Attributs & MOD_VIRTUAL ) + fprintf( aFile, "VIRTUAL " ); + + fprintf( aFile, "\n" ); + } + + // save reference + if( !m_Reference->Save( aFile ) ) + goto out; + + // save value + if( !m_Value->Save( aFile ) ) + goto out; + + // save drawing elements + for( item = m_Drawings; item; item = item->Next() ) + { + switch( item->Type() ) + { + case PCB_MODULE_TEXT_T: + case PCB_MODULE_EDGE_T: + if( !item->Save( aFile ) ) + goto out; + + break; + + default: +#if defined(DEBUG) + printf( "MODULE::Save() ignoring type %d\n", item->Type() ); +#endif + break; + } + } + + // save the pads + for( item = m_Pads; item; item = item->Next() ) + if( !item->Save( aFile ) ) + goto out; + + Write_3D_Descr( aFile ); + + fprintf( aFile, "$EndMODULE %s\n", TO_UTF8( m_LibRef ) ); + + rc = true; +out: + return rc; +} + +/* Save the description of 3D MODULE + */ +int MODULE::Write_3D_Descr( FILE* File ) const +{ + char buf[512]; + + for( S3D_MASTER* t3D = m_3D_Drawings; t3D; t3D = t3D->Next() ) + { + if( !t3D->m_Shape3DName.IsEmpty() ) + { + fprintf( File, "$SHAPE3D\n" ); + + fprintf( File, "Na %s\n", EscapedUTF8( t3D->m_Shape3DName ).c_str() ); + + sprintf( buf, "Sc %lf %lf %lf\n", + t3D->m_MatScale.x, + t3D->m_MatScale.y, + t3D->m_MatScale.z ); + fprintf( File, "%s", to_point( buf ) ); + + sprintf( buf, "Of %lf %lf %lf\n", + t3D->m_MatPosition.x, + t3D->m_MatPosition.y, + t3D->m_MatPosition.z ); + fprintf( File, "%s", to_point( buf ) ); + + sprintf( buf, "Ro %lf %lf %lf\n", + t3D->m_MatRotation.x, + t3D->m_MatRotation.y, + t3D->m_MatRotation.z ); + fprintf( File, "%s", to_point( buf ) ); + + fprintf( File, "$EndSHAPE3D\n" ); + } + } + + return 0; +} + +#endif // USE_NEW_PCBNEW_SAVE + + +#if !defined(USE_NEW_PCBNEW_LOAD) + +/* Read pad from file. + * The 1st line of descr ($PAD) is assumed to be already read + * Syntax: + * $PAD + * Sh "N1" C 550 550 0 0 1800 + * Dr 310 0 0 + * At STD N 00C0FFFF + * Do 3 "netname" + * Po 6000 -6000 + * $EndPAD + */ +int D_PAD::ReadDescr( LINE_READER* aReader ) +{ + char* Line; + char BufLine[1024], BufCar[256]; + char* PtLine; + int nn, ll, dx, dy; + + while( aReader->ReadLine() ) + { + Line = aReader->Line(); + + if( Line[0] == '$' ) + return 0; + + PtLine = Line + 3; + + /* Decode the first code and read the corresponding data + */ + switch( Line[0] ) + { + case 'S': // = Sh + /* Read pad name */ + nn = 0; + + while( (*PtLine != '"') && *PtLine ) + PtLine++; + + if( *PtLine ) + PtLine++; + + memset( m_Padname, 0, sizeof(m_Padname) ); + + while( (*PtLine != '"') && *PtLine ) + { + if( nn < (int) sizeof(m_Padname) ) + { + if( *PtLine > ' ' ) + { + m_Padname[nn] = *PtLine; nn++; + } + } + PtLine++; + } + + if( *PtLine == '"' ) + PtLine++; + + nn = sscanf( PtLine, " %s %d %d %d %d %d", + BufCar, &m_Size.x, &m_Size.y, + &m_DeltaSize.x, &m_DeltaSize.y, + &m_Orient ); + + ll = 0xFF & BufCar[0]; + + /* Read pad shape */ + m_PadShape = PAD_CIRCLE; + + switch( ll ) + { + case 'C': + m_PadShape = PAD_CIRCLE; break; + + case 'R': + m_PadShape = PAD_RECT; break; + + case 'O': + m_PadShape = PAD_OVAL; break; + + case 'T': + m_PadShape = PAD_TRAPEZOID; break; + } + + ComputeShapeMaxRadius(); + break; + + case 'D': + BufCar[0] = 0; + nn = sscanf( PtLine, "%d %d %d %s %d %d", &m_Drill.x, + &m_Offset.x, &m_Offset.y, BufCar, &dx, &dy ); + m_Drill.y = m_Drill.x; + m_DrillShape = PAD_CIRCLE; + + if( nn >= 6 ) // Drill shape = OVAL ? + { + if( BufCar[0] == 'O' ) + { + m_Drill.x = dx; m_Drill.y = dy; + m_DrillShape = PAD_OVAL; + } + } + + break; + + case 'A': + nn = sscanf( PtLine, "%s %s %X", BufLine, BufCar, + &m_layerMask ); + + /* BufCar is not used now update attributes */ + m_Attribut = PAD_STANDARD; + if( strncmp( BufLine, "SMD", 3 ) == 0 ) + m_Attribut = PAD_SMD; + + if( strncmp( BufLine, "CONN", 4 ) == 0 ) + m_Attribut = PAD_CONN; + + if( strncmp( BufLine, "HOLE", 4 ) == 0 ) + m_Attribut = PAD_HOLE_NOT_PLATED; + + break; + + case 'N': /* Read Netname */ + int netcode; + nn = sscanf( PtLine, "%d", &netcode ); + SetNet( netcode ); + + /* read Netname */ + ReadDelimitedText( BufLine, PtLine, sizeof(BufLine) ); + SetNetname( FROM_UTF8( StrPurge( BufLine ) ) ); + break; + + case 'P': + nn = sscanf( PtLine, "%d %d", &m_Pos0.x, &m_Pos0.y ); + m_Pos = m_Pos0; + break; + + case 'L': + int lengthdie; + nn = sscanf( PtLine, "%d", &lengthdie ); + m_LengthDie = lengthdie; + break; + + case '.': /* Read specific data */ + if( strnicmp( Line, ".SolderMask ", 12 ) == 0 ) + m_LocalSolderMaskMargin = atoi( Line + 12 ); + else if( strnicmp( Line, ".SolderPaste ", 13 ) == 0 ) + m_LocalSolderPasteMargin = atoi( Line + 13 ); + else if( strnicmp( Line, ".SolderPasteRatio ", 18 ) == 0 ) + m_LocalSolderPasteMarginRatio = atoi( Line + 18 ); + else if( strnicmp( Line, ".LocalClearance ", 16 ) == 0 ) + m_LocalClearance = atoi( Line + 16 ); + break; + + default: + DisplayError( NULL, wxT( "Err Pad: Id inconnu" ) ); + return 1; + } + } + + return 2; /* error : EOF */ +} + + +/* Read 3D module from file. (Ascii) + * The 1st line of descr ($MODULE) is assumed to be already read + * Returns 0 if OK + */ +int MODULE::Read_3D_Descr( LINE_READER* aReader ) +{ + char* Line = aReader->Line(); + char* text = Line + 3; + + S3D_MASTER* t3D = m_3D_Drawings; + + if( !t3D->m_Shape3DName.IsEmpty() ) + { + S3D_MASTER* n3D = new S3D_MASTER( this ); + + m_3D_Drawings.PushBack( n3D ); + + t3D = n3D; + } + + while( aReader->ReadLine() ) + { + Line = aReader->Line(); + + switch( Line[0] ) + { + case '$': + if( Line[1] == 'E' ) + return 0; + + return 1; + + case 'N': // Shape File Name + { + char buf[512]; + ReadDelimitedText( buf, text, 512 ); + t3D->m_Shape3DName = FROM_UTF8( buf ); + break; + } + + case 'S': // Scale + sscanf( text, "%lf %lf %lf\n", + &t3D->m_MatScale.x, + &t3D->m_MatScale.y, + &t3D->m_MatScale.z ); + break; + + case 'O': // Offset + sscanf( text, "%lf %lf %lf\n", + &t3D->m_MatPosition.x, + &t3D->m_MatPosition.y, + &t3D->m_MatPosition.z ); + break; + + case 'R': // Rotation + sscanf( text, "%lf %lf %lf\n", + &t3D->m_MatRotation.x, + &t3D->m_MatRotation.y, + &t3D->m_MatRotation.z ); + break; + + default: + break; + } + } + + return 1; +} + + +/* Read a MODULE description + * The first description line ($MODULE) is already read + * @return 0 if no error + */ +int MODULE::ReadDescr( LINE_READER* aReader ) +{ + char* Line; + char BufLine[256], BufCar1[128], * PtLine; + int itmp1, itmp2; + + while( aReader->ReadLine() ) + { + Line = aReader->Line(); + if( Line[0] == '$' ) + { + if( Line[1] == 'E' ) + break; + + if( Line[1] == 'P' ) + { + D_PAD* pad = new D_PAD( this ); + pad->ReadDescr( aReader ); + RotatePoint( &pad->m_Pos, m_Orient ); + pad->m_Pos.x += m_Pos.x; + pad->m_Pos.y += m_Pos.y; + + m_Pads.PushBack( pad ); + continue; + } + + if( Line[1] == 'S' ) + Read_3D_Descr( aReader ); + } + + if( strlen( Line ) < 4 ) + continue; + + PtLine = Line + 3; + + /* Decode the first code of the current line and read the + * corresponding data + */ + switch( Line[0] ) + { + case 'P': + memset( BufCar1, 0, sizeof(BufCar1) ); + sscanf( PtLine, "%d %d %d %d %lX %lX %s", + &m_Pos.x, &m_Pos.y, + &m_Orient, &m_Layer, + &m_LastEdit_Time, &m_TimeStamp, BufCar1 ); + + m_ModuleStatus = 0; + + if( BufCar1[0] == 'F' ) + SetLocked( true ); + + if( BufCar1[1] == 'P' ) + m_ModuleStatus |= MODULE_is_PLACED; + + break; + + case 'L': /* Li = read the library name of the footprint */ + *BufLine = 0; + sscanf( PtLine, " %s", BufLine ); + m_LibRef = FROM_UTF8( BufLine ); + break; + + case 'S': + sscanf( PtLine, " %lX", &m_TimeStamp ); + break; + + + case 'O': /* (Op)tions for auto placement */ + itmp1 = itmp2 = 0; + sscanf( PtLine, " %X %X", &itmp1, &itmp2 ); + + m_CntRot180 = itmp2 & 0x0F; + + if( m_CntRot180 > 10 ) + m_CntRot180 = 10; + + m_CntRot90 = itmp1 & 0x0F; + + if( m_CntRot90 > 10 ) + m_CntRot90 = 0; + + itmp1 = (itmp1 >> 4) & 0x0F; + + if( itmp1 > 10 ) + itmp1 = 0; + + m_CntRot90 |= itmp1 << 4; + break; + + case 'A': + if( Line[1] == 't' ) + { + /* At = (At)tributes of module */ + if( strstr( PtLine, "SMD" ) ) + m_Attributs |= MOD_CMS; + + if( strstr( PtLine, "VIRTUAL" ) ) + m_Attributs |= MOD_VIRTUAL; + } + + if( Line[1] == 'R' ) + { + // alternate reference, e.g. /478C2408/478AD1B6 + sscanf( PtLine, " %s", BufLine ); + m_Path = FROM_UTF8( BufLine ); + } + + break; + + case 'T': /* Read a footprint text description (ref, value, or + * drawing */ + TEXTE_MODULE * textm; + sscanf( Line + 1, "%d", &itmp1 ); + + if( itmp1 == TEXT_is_REFERENCE ) + textm = m_Reference; + else if( itmp1 == TEXT_is_VALUE ) + textm = m_Value; + else /* text is a drawing */ + { + textm = new TEXTE_MODULE( this ); + m_Drawings.PushBack( textm ); + } + textm->ReadDescr( aReader ); + break; + + case 'D': /* read a drawing item */ + EDGE_MODULE * edge; + edge = new EDGE_MODULE( this ); + m_Drawings.PushBack( edge ); + edge->ReadDescr( aReader ); + edge->SetDrawCoord(); + break; + + case 'C': /* read documentation data */ + m_Doc = FROM_UTF8( StrPurge( PtLine ) ); + break; + + case 'K': /* Read key words */ + m_KeyWord = FROM_UTF8( StrPurge( PtLine ) ); + break; + + case '.': /* Read specific data */ + if( strnicmp( Line, ".SolderMask ", 12 ) == 0 ) + m_LocalSolderMaskMargin = atoi( Line + 12 ); + else if( strnicmp( Line, ".SolderPaste ", 13 ) == 0 ) + m_LocalSolderPasteMargin = atoi( Line + 13 ); + else if( strnicmp( Line, ".SolderPasteRatio ", 18 ) == 0 ) + m_LocalSolderPasteMarginRatio = atof( Line + 18 ); + else if( strnicmp( Line, ".LocalClearance ", 16 ) == 0 ) + m_LocalClearance = atoi( Line + 16 ); + + break; + + default: + break; + } + } + + /* Recalculate the bounding box */ + CalculateBoundingBox(); + return 0; +} + + +/* Read a description line like: + * DS 2600 0 2600 -600 120 21 + * this description line is in Line + * EDGE_MODULE type can be: + * - Circle, + * - Segment (line) + * - Arc + * - Polygon + * + */ +int EDGE_MODULE::ReadDescr( LINE_READER* aReader ) +{ + int ii; + int error = 0; + char* Buf; + char* Line; + + Line = aReader->Line(); + + switch( Line[1] ) + { + case 'S': + m_Shape = S_SEGMENT; + break; + + case 'C': + m_Shape = S_CIRCLE; + break; + + case 'A': + m_Shape = S_ARC; + break; + + case 'P': + m_Shape = S_POLYGON; + break; + + default: + wxString msg; + msg.Printf( wxT( "Unknown EDGE_MODULE type <%s>" ), Line ); + DisplayError( NULL, msg ); + error = 1; + break; + } + + switch( m_Shape ) + { + case S_ARC: + sscanf( Line + 3, "%d %d %d %d %d %d %d", + &m_Start0.x, &m_Start0.y, + &m_End0.x, &m_End0.y, + &m_Angle, &m_Width, &m_Layer ); + NORMALIZE_ANGLE_360( m_Angle ); + break; + + case S_SEGMENT: + case S_CIRCLE: + sscanf( Line + 3, "%d %d %d %d %d %d", + &m_Start0.x, &m_Start0.y, + &m_End0.x, &m_End0.y, + &m_Width, &m_Layer ); + break; + + case S_POLYGON: + int pointCount; + sscanf( Line + 3, "%d %d %d %d %d %d %d", + &m_Start0.x, &m_Start0.y, + &m_End0.x, &m_End0.y, + &pointCount, &m_Width, &m_Layer ); + + m_PolyPoints.clear(); + m_PolyPoints.reserve( pointCount ); + + for( ii = 0; iiReadLine() ) + { + Buf = aReader->Line(); + + if( strncmp( Buf, "Dl", 2 ) != 0 ) + { + error = 1; + break; + } + + int x; + int y; + sscanf( Buf + 3, "%d %d\n", &x, &y ); + + m_PolyPoints.push_back( wxPoint( x, y ) ); + } + else + { + error = 1; + break; + } + } + + break; + + default: + sscanf( Line + 3, "%d %d %d %d %d %d", + &m_Start0.x, &m_Start0.y, + &m_End0.x, &m_End0.y, + &m_Width, &m_Layer ); + break; + } + + // Check for a reasonable width: + if( m_Width <= 1 ) + m_Width = 1; + + if( m_Width > MAX_WIDTH ) + m_Width = MAX_WIDTH; + + // Check for a reasonable layer: + // m_Layer must be >= FIRST_NON_COPPER_LAYER, but because microwave footprints + // can use the copper layers m_Layer < FIRST_NON_COPPER_LAYER is allowed. + // @todo: changes use of EDGE_MODULE these footprints and allows only + // m_Layer >= FIRST_NON_COPPER_LAYER + if( (m_Layer < 0) || (m_Layer > LAST_NON_COPPER_LAYER) ) + m_Layer = SILKSCREEN_N_FRONT; + + return error; +} + + +bool DIMENSION::ReadDimensionDescr( LINE_READER* aReader ) +{ + char* Line; + char Text[2048]; + + while( aReader->ReadLine() ) + { + Line = aReader->Line(); + + if( strnicmp( Line, "$EndDIMENSION", 4 ) == 0 ) + return true; + + if( Line[0] == 'V' ) + { + sscanf( Line + 2, " %d", &m_Value ); + continue; + } + + if( Line[0] == 'G' ) + { + int layer; + + sscanf( Line + 2, " %d %d %lX", &m_Shape, &layer, &m_TimeStamp ); + + if( layer < FIRST_NO_COPPER_LAYER ) + layer = FIRST_NO_COPPER_LAYER; + + if( layer > LAST_NO_COPPER_LAYER ) + layer = LAST_NO_COPPER_LAYER; + + SetLayer( layer ); + m_Text->SetLayer( layer ); + continue; + } + + if( Line[0] == 'T' ) + { + ReadDelimitedText( Text, Line + 2, sizeof(Text) ); + m_Text->m_Text = FROM_UTF8( Text ); + continue; + } + + if( Line[0] == 'P' ) + { + int normal_display = 1; + int orientation; + int thickness; + sscanf( Line + 2, " %d %d %d %d %d %d %d", + &m_Text->m_Pos.x, &m_Text->m_Pos.y, + &m_Text->m_Size.x, &m_Text->m_Size.y, + &thickness, &orientation, + &normal_display ); + + m_Text->m_Mirror = normal_display ? false : true; + m_Pos = m_Text->m_Pos; + m_Text->SetOrientation( orientation ); + m_Text->SetThickness( thickness ); + continue; + } + + if( Line[0] == 'S' ) + { + switch( Line[1] ) + { + int Dummy; + + case 'b': + sscanf( Line + 2, " %d %d %d %d %d %d", + &Dummy, + &m_crossBarOx, &m_crossBarOy, + &m_crossBarFx, &m_crossBarFy, + &m_Width ); + break; + + case 'd': + sscanf( Line + 2, " %d %d %d %d %d %d", + &Dummy, + &m_featureLineDOx, &m_featureLineDOy, + &m_featureLineDFx, &m_featureLineDFy, + &Dummy ); + break; + + case 'g': + sscanf( Line + 2, " %d %d %d %d %d %d", + &Dummy, + &m_featureLineGOx, &m_featureLineGOy, + &m_featureLineGFx, &m_featureLineGFy, + &Dummy ); + break; + + case '1': + sscanf( Line + 2, " %d %d %d %d %d %d", + &Dummy, + &m_arrowD1Ox, &m_arrowD1Oy, + &m_arrowD1Fx, &m_arrowD1Fy, + &Dummy ); + break; + + case '2': + sscanf( Line + 2, " %d %d %d %d %d %d", + &Dummy, + &m_arrowD2Ox, &m_arrowD2Oy, + &m_arrowD2Fx, &m_arrowD2Fy, + &Dummy ); + break; + + case '3': + sscanf( Line + 2, " %d %d %d %d %d %d\n", + &Dummy, + &m_arrowG1Ox, &m_arrowG1Oy, + &m_arrowG1Fx, &m_arrowG1Fy, + &Dummy ); + break; + + case '4': + sscanf( Line + 2, " %d %d %d %d %d %d", + &Dummy, + &m_arrowG2Ox, &m_arrowG2Oy, + &m_arrowG2Fx, &m_arrowG2Fy, + &Dummy ); + break; + } + + continue; + } + } + + return false; +} + + +bool DRAWSEGMENT::ReadDrawSegmentDescr( LINE_READER* aReader ) +{ + char* Line; + + while( aReader->ReadLine() ) + { + Line = aReader->Line(); + + if( strnicmp( Line, "$End", 4 ) == 0 ) + return true; /* End of description */ + + if( Line[0] == 'P' ) + { + sscanf( Line + 2, " %d %d %d %d %d %d", + &m_Shape, &m_Start.x, &m_Start.y, + &m_End.x, &m_End.y, &m_Width ); + + if( m_Width < 0 ) + m_Width = 0; + } + + if( Line[0] == 'D' ) + { + int status; + char* token = 0; + + token = strtok( Line," " ); + + for( int i = 0; (token = strtok( NULL," " )) != NULL; i++ ) + { + switch( i ) + { + case 0: + sscanf( token,"%d",&m_Layer ); + break; + case 1: + sscanf( token,"%d",&m_Type ); + break; + case 2: + sscanf( token,"%d",&m_Angle ); + break; + case 3: + sscanf( token,"%lX",&m_TimeStamp ); + break; + case 4: + sscanf( token,"%X",&status ); + break; + /* Bezier Control Points*/ + case 5: + sscanf( token,"%d",&m_BezierC1.x ); + break; + case 6: + sscanf( token,"%d",&m_BezierC1.y ); + break; + case 7: + sscanf( token,"%d",&m_BezierC2.x ); + break; + case 8: + sscanf( token,"%d",&m_BezierC2.y ); + break; + default: + break; + } + } + + if( m_Layer < FIRST_NO_COPPER_LAYER ) + m_Layer = FIRST_NO_COPPER_LAYER; + + if( m_Layer > LAST_NO_COPPER_LAYER ) + m_Layer = LAST_NO_COPPER_LAYER; + + SetState( status, ON ); + } + } + + return false; +} + + +/* Read NETINFO_ITEM from file. + * Returns 0 if OK + * 1 if incomplete reading + */ +int NETINFO_ITEM::ReadDescr( LINE_READER* aReader ) +{ + char* Line; + char Ltmp[1024]; + int tmp; + + while( aReader->ReadLine() ) + { + Line = aReader->Line(); + if( strnicmp( Line, "$End", 4 ) == 0 ) + return 0; + + if( strncmp( Line, "Na", 2 ) == 0 ) + { + sscanf( Line + 2, " %d", &tmp ); + SetNet( tmp ); + + ReadDelimitedText( Ltmp, Line + 2, sizeof(Ltmp) ); + m_Netname = FROM_UTF8( Ltmp ); + continue; + } + } + + return 1; +} + + +/* Read the description from the PCB file. + */ +bool PCB_TARGET::ReadMirePcbDescr( LINE_READER* aReader ) +{ + char* Line; + + while( aReader->ReadLine() ) + { + Line = aReader->Line(); + + if( strnicmp( Line, "$End", 4 ) == 0 ) + return true; + + if( Line[0] == 'P' ) + { + sscanf( Line + 2, " %X %d %d %d %d %d %lX", + &m_Shape, &m_Layer, + &m_Pos.x, &m_Pos.y, + &m_Size, &m_Width, &m_TimeStamp ); + + if( m_Layer < FIRST_NO_COPPER_LAYER ) + m_Layer = FIRST_NO_COPPER_LAYER; + + if( m_Layer > LAST_NO_COPPER_LAYER ) + m_Layer = LAST_NO_COPPER_LAYER; + } + } + + return false; +} + + +int ZONE_CONTAINER::ReadDescr( LINE_READER* aReader ) +{ + char* Line, * text; + char netname_buffer[1024]; + int ret; + int outline_hatch = CPolyLine::NO_HATCH; + bool error = false, has_corner = false; + + netname_buffer[0] = 0; + + while( aReader->ReadLine() ) + { + Line = aReader->Line(); + + if( strnicmp( Line, "ZCorner", 7 ) == 0 ) // new corner found + { + int x; + int y; + int flag; + + text = Line + 7; + ret = sscanf( text, "%d %d %d", &x, &y, &flag ); + + if( ret < 3 ) + { + error = true; + } + else + { + if( !has_corner ) + m_Poly->Start( m_Layer, x, y, outline_hatch ); + else + AppendCorner( wxPoint( x, y ) ); + + has_corner = true; + + if( flag ) + m_Poly->Close(); + } + } + else if( strnicmp( Line, "ZInfo", 5 ) == 0 ) // general info found + { + int ts; + int netcode; + + text = Line + 5; + ret = sscanf( text, "%X %d %s", &ts, &netcode, netname_buffer ); + + if( ret < 3 ) + { + error = true; + } + else + { + m_TimeStamp = ts; + m_NetCode = netcode; + ReadDelimitedText( netname_buffer, netname_buffer, 1024 ); + m_Netname = FROM_UTF8( netname_buffer ); + } + } + else if( strnicmp( Line, "ZLayer", 6 ) == 0 ) // layer found + { + int x; + + text = Line + 6; + ret = sscanf( text, "%d", &x ); + + if( ret < 1 ) + error = true; + else + m_Layer = x; + } + else if( strnicmp( Line, "ZAux", 4 ) == 0 ) // aux info found + { + int x; + char hopt[10]; + + text = Line + 4; + ret = sscanf( text, "%d %c", &x, hopt ); + + if( ret < 2 ) + { + error = true; + } + else + { + switch( hopt[0] ) + { + case 'n': + case 'N': + outline_hatch = CPolyLine::NO_HATCH; + break; + + case 'e': + case 'E': + outline_hatch = CPolyLine::DIAGONAL_EDGE; + break; + + case 'f': + case 'F': + outline_hatch = CPolyLine::DIAGONAL_FULL; + break; + } + } + /* Set hatch mode later, after reading outlines corners data */ + } + else if( strnicmp( Line, "ZSmoothing", 10 ) == 0 ) + { + int tempSmoothingType; + int tempCornerRadius; + text = Line + 10; + ret = sscanf( text, "%d %d", &tempSmoothingType, &tempCornerRadius ); + + if( ret < 2 ) + return false; + + if( tempSmoothingType >= ZONE_SETTING::SMOOTHING_LAST) + return false; + + if( tempSmoothingType < 0 ) + return false; + + cornerSmoothingType = tempSmoothingType; + SetCornerRadius( tempCornerRadius ); + } + else if( strnicmp( Line, "ZOptions", 8 ) == 0 ) // Options info found + { + int fillmode = 1; + int arcsegmentcount = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF; + char fillstate = 'F'; + text = Line + 8; + ret = sscanf( text, "%d %d %c %d %d", &fillmode, &arcsegmentcount, &fillstate, + &m_ThermalReliefGap, &m_ThermalReliefCopperBridge ); + + if( ret < 1 ) // Must find 1 or more args. + return false; + else + m_FillMode = fillmode ? 1 : 0; + + if( arcsegmentcount >= ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF ) + m_ArcToSegmentsCount = ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF; + + m_IsFilled = (fillstate == 'S') ? true : false; + } + else if( strnicmp( Line, "ZClearance", 10 ) == 0 ) // Clearance and pad options info found + { + int clearance = 200; + char padoption; + text = Line + 10; + ret = sscanf( text, "%d %1c", &clearance, &padoption ); + + if( ret < 2 ) + { + error = true; + } + else + { + m_ZoneClearance = clearance; + + switch( padoption ) + { + case 'i': + case 'I': + m_PadOption = PAD_IN_ZONE; + break; + + case 't': + case 'T': + m_PadOption = THERMAL_PAD; + break; + + case 'x': + case 'X': + m_PadOption = PAD_NOT_IN_ZONE; + break; + } + } + } + else if( strnicmp( Line, "ZMinThickness", 13 ) == 0 ) // Min Thickness info found + { + int thickness; + text = Line + 13; + ret = sscanf( text, "%d", &thickness ); + + if( ret < 1 ) + error = true; + else + m_ZoneMinThickness = thickness; + } + else if( strnicmp( Line, "$POLYSCORNERS", 13 ) == 0 ) // Read the PolysList (polygons used for fill areas in the zone) + { + while( aReader->ReadLine() ) + { + Line = aReader->Line(); + + if( strnicmp( Line, "$endPOLYSCORNERS", 4 ) == 0 ) + break; + + CPolyPt corner; + int end_contour, utility; + utility = 0; + ret = sscanf( Line, + "%d %d %d %d", + &corner.x, + &corner.y, + &end_contour, + &utility ); + if( ret < 4 ) + return false; + + corner.end_contour = end_contour ? true : false; + corner.utility = utility; + m_FilledPolysList.push_back( corner ); + } + } + else if( strnicmp( Line, "$FILLSEGMENTS", 13 ) == 0 ) + { + SEGMENT segm; + while( aReader->ReadLine() ) + { + Line = aReader->Line(); + + if( strnicmp( Line, "$endFILLSEGMENTS", 4 ) == 0 ) + break; + + ret = sscanf( Line, + "%d %d %d %d", + &segm.m_Start.x, + &segm.m_Start.y, + &segm.m_End.x, + &segm.m_End.y ); + if( ret < 4 ) + return false; + + m_FillSegmList.push_back( segm ); + } + } + else if( strnicmp( Line, "$end", 4 ) == 0 ) // end of description + { + break; + } + } + + if( !IsOnCopperLayer() ) + { + m_FillMode = 0; + SetNet( 0 ); + } + + /* Set hatch here, when outlines corners are read */ + m_Poly->SetHatch( outline_hatch ); + + return error ? 0 : 1; +} + + +bool NETCLASS::ReadDescr( LINE_READER* aReader ) +{ + bool result = false; + char* line; + char buf[1024]; + wxString netname; + + while( aReader->ReadLine() ) + { + line = aReader->Line(); + if( strnicmp( line, "AddNet", 6 ) == 0 ) + { + ReadDelimitedText( buf, line + 6, sizeof(buf) ); + netname = FROM_UTF8( buf ); + Add( netname ); + continue; + } + + if( strnicmp( line, "$endNCLASS", sizeof( "$endNCLASS" ) - 1 ) == 0 ) + { + result = true; + break; + } + + if( strnicmp( line, "Clearance", 9 ) == 0 ) + { + SetClearance( atoi( line + 9 ) ); + continue; + } + if( strnicmp( line, "TrackWidth", 10 ) == 0 ) + { + SetTrackWidth( atoi( line + 10 ) ); + continue; + } + if( strnicmp( line, "ViaDia", 6 ) == 0 ) + { + SetViaDiameter( atoi( line + 6 ) ); + continue; + } + if( strnicmp( line, "ViaDrill", 8 ) == 0 ) + { + SetViaDrill( atoi( line + 8 ) ); + continue; + } + + if( strnicmp( line, "uViaDia", 7 ) == 0 ) + { + SetuViaDiameter( atoi( line + 7 ) ); + continue; + } + if( strnicmp( line, "uViaDrill", 9 ) == 0 ) + { + SetuViaDrill( atoi( line + 9 ) ); + continue; + } + + if( strnicmp( line, "Name", 4 ) == 0 ) + { + ReadDelimitedText( buf, line + 4, sizeof(buf) ); + m_Name = FROM_UTF8( buf ); + continue; + } + if( strnicmp( line, "Desc", 4 ) == 0 ) + { + ReadDelimitedText( buf, line + 4, sizeof(buf) ); + SetDescription( FROM_UTF8( buf ) ); + continue; + } + } + + return result; +} + + + +/** + * Function ReadTextePcbDescr + * Read a text description from pcb file. + * + * For a single line text: + * + * $TEXTPCB + * Te "Text example" + * Po 66750 53450 600 800 150 0 + * From 24 1 0 Italic + * $EndTEXTPCB + * + * For a multi line text + * + * $TEXTPCB + * Te "Text example" + * Nl "Line 2" + * Po 66750 53450 600 800 150 0 + * From 24 1 0 Italic + * $EndTEXTPCB + * Nl "line nn" is a line added to the current text + */ +int TEXTE_PCB::ReadTextePcbDescr( LINE_READER* aReader ) +{ + char* line; + char text[1024]; + char style[256]; + + while( aReader->ReadLine() ) + { + line = aReader->Line(); + if( strnicmp( line, "$EndTEXTPCB", 11 ) == 0 ) + return 0; + if( strncmp( line, "Te", 2 ) == 0 ) /* Text line (first line for multi line texts */ + { + ReadDelimitedText( text, line + 2, sizeof(text) ); + m_Text = FROM_UTF8( text ); + continue; + } + if( strncmp( line, "nl", 2 ) == 0 ) /* next line of the current text */ + { + ReadDelimitedText( text, line + 2, sizeof(text) ); + m_Text.Append( '\n' ); + m_Text += FROM_UTF8( text ); + continue; + } + if( strncmp( line, "Po", 2 ) == 0 ) + { + sscanf( line + 2, " %d %d %d %d %d %d", + &m_Pos.x, &m_Pos.y, &m_Size.x, &m_Size.y, + &m_Thickness, &m_Orient ); + + // Ensure the text has minimal size to see this text on screen: + if( m_Size.x < 5 ) + m_Size.x = 5; + if( m_Size.y < 5 ) + m_Size.y = 5; + continue; + } + if( strncmp( line, "De", 2 ) == 0 ) + { + style[0] = 0; + int normal_display = 1; + char hJustify = 'c'; + sscanf( line + 2, " %d %d %lX %s %c\n", &m_Layer, &normal_display, + &m_TimeStamp, style, &hJustify ); + + m_Mirror = normal_display ? false : true; + + if( m_Layer < FIRST_COPPER_LAYER ) + m_Layer = FIRST_COPPER_LAYER; + if( m_Layer > LAST_NO_COPPER_LAYER ) + m_Layer = LAST_NO_COPPER_LAYER; + + if( strnicmp( style, "Italic", 6 ) == 0 ) + m_Italic = 1; + else + m_Italic = 0; + + switch( hJustify ) + { + case 'l': + case 'L': + m_HJustify = GR_TEXT_HJUSTIFY_LEFT; + break; + case 'c': + case 'C': + m_HJustify = GR_TEXT_HJUSTIFY_CENTER; + break; + case 'r': + case 'R': + m_HJustify = GR_TEXT_HJUSTIFY_RIGHT; + break; + default: + m_HJustify = GR_TEXT_HJUSTIFY_CENTER; + break; + } + continue; + } + } + + // Set a reasonable width: + if( m_Thickness < 1 ) + m_Thickness = 1; + m_Thickness = Clamp_Text_PenSize( m_Thickness, m_Size ); + + return 1; +} + +/** + * Function ReadDescr + * Read description from a given line in "*.brd" format. + * @param aReader The line reader object which contains the first line of description. + * @return int - > 0 if success reading else 0. + */ +int TEXTE_MODULE::ReadDescr( LINE_READER* aReader ) +{ + int success = true; + int type; + char BufCar1[128], BufCar2[128], BufCar3[128]; + char* line = aReader->Line(); + + int layer = SILKSCREEN_N_FRONT; + + BufCar1[0] = 0; + BufCar2[0] = 0; + BufCar3[0] = 0; + + if( sscanf( line + 1, "%d %d %d %d %d %d %d %s %s %d %s", + &type, + &m_Pos0.x, &m_Pos0.y, + &m_Size.y, &m_Size.x, + &m_Orient, &m_Thickness, + BufCar1, BufCar2, &layer, BufCar3 ) >= 10 ) + { + success = true; + } + + if( (type != TEXT_is_REFERENCE) && (type != TEXT_is_VALUE) ) + type = TEXT_is_DIVERS; + + m_Type = type; + + // Due to the Pcbnew history, .m_Orient is saved in screen value + // but it is handled as relative to its parent footprint + m_Orient -= ( (MODULE*) m_Parent )->m_Orient; + + if( BufCar1[0] == 'M' ) + m_Mirror = true; + else + m_Mirror = false; + + if( BufCar2[0] == 'I' ) + m_NoShow = true; + else + m_NoShow = false; + + if( BufCar3[0] == 'I' ) + m_Italic = true; + else + m_Italic = false; + + // Test for a reasonable layer: + if( layer < 0 ) + layer = 0; + if( layer > LAST_NO_COPPER_LAYER ) + layer = LAST_NO_COPPER_LAYER; + if( layer == LAYER_N_BACK ) + layer = SILKSCREEN_N_BACK; + else if( layer == LAYER_N_FRONT ) + layer = SILKSCREEN_N_FRONT; + + SetLayer( layer ); + + // Calculate the actual position. + SetDrawCoord(); + + + // Search and read the "text" string (a quoted text). + ReadDelimitedText( &m_Text, line ); + + // Test for a reasonable size: + if( m_Size.x < TEXTS_MIN_SIZE ) + m_Size.x = TEXTS_MIN_SIZE; + if( m_Size.y < TEXTS_MIN_SIZE ) + m_Size.y = TEXTS_MIN_SIZE; + + // Set a reasonable width: + if( m_Thickness < 1 ) + m_Thickness = 1; + m_Thickness = Clamp_Text_PenSize( m_Thickness, m_Size ); + + return success; +} + +#endif // USE_NEW_PCBNEW_LOAD diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index feb1707beb..c239b1d4ee 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -88,6 +88,8 @@ #include +#include + #define VERSION_ERROR_FORMAT _( "File '%s' is format version %d.\nI only support format version <= %d.\nPlease upgrade PCBNew to load this file." ) /* @@ -2520,8 +2522,867 @@ void KICAD_PLUGIN::init( PROPERTIES* aProperties ) } +//------------------------------------------------------------ + void KICAD_PLUGIN::Save( const wxString& aFileName, BOARD* aBoard, PROPERTIES* aProperties ) { - LOCALE_IO toggle; // toggles on then off the C locale. + LOCALE_IO toggle; // toggles on, then off, the C locale. + + m_board = aBoard; + + FILE* fp = wxFopen( aFileName, wxT( "wt" ) ); + if( !fp ) + { + m_error.Printf( _( "Unable to open file '%s'" ), aFileName.GetData() ); + THROW_IO_ERROR( m_error ); + } + + // wxf now owns fp, will close on exception or return + wxFFile wxf( fp ); + + m_fp = fp; // member function accessibility + + init( aProperties ); + +// saveAllSections(); } + +#if 0 +void KICAD_PLUGIN::saveAllSections() const +{ + // $GENERAL section is first + + // $SHEETDESCR section is next + + // $SETUP section is next + + // Then follows $EQUIPOT and all the rest + saveBOARD(); +} + + +void KICAD_PLUGIN::saveBOARD() const +{ + bool rc = false; + BOARD_ITEM* item; + + // save the nets + for( unsigned ii = 0; ii < m_NetInfo->GetCount(); ii++ ) + if( !m_NetInfo->GetNetItem( ii )->Save( aFile ) ) + goto out; + + // Saved nets do not include netclass names, so save netclasses after nets. + m_NetClasses.Save( aFile ); + + // save the modules + for( item = m_Modules; item; item = item->Next() ) + if( !item->Save( aFile ) ) + goto out; + + for( item = m_Drawings; item; item = item->Next() ) + { + switch( item->Type() ) + { + case PCB_TEXT_T: + case PCB_LINE_T: + case PCB_TARGET_T: + case PCB_DIMENSION_T: + if( !item->Save( aFile ) ) + goto out; + + break; + + default: + + // future: throw exception here +#if defined(DEBUG) + printf( "BOARD::Save() ignoring m_Drawings type %d\n", item->Type() ); +#endif + break; + } + } + + // do not save MARKER_PCBs, they can be regenerated easily + + // save the tracks & vias + fprintf( aFile, "$TRACK\n" ); + + for( item = m_Track; item; item = item->Next() ) + { + if( !item->Save( aFile ) ) + goto out; + } + + fprintf( aFile, "$EndTRACK\n" ); + + // save the zones + fprintf( aFile, "$ZONE\n" ); + + for( item = m_Zone; item; item = item->Next() ) + { + if( !item->Save( aFile ) ) + goto out; + } + + fprintf( aFile, "$EndZONE\n" ); + + // save the zone edges + for( unsigned ii = 0; ii < m_ZoneDescriptorList.size(); ii++ ) + { + ZONE_CONTAINER* edge_zone = m_ZoneDescriptorList[ii]; + edge_zone->Save( aFile ); + } + + + if( fprintf( aFile, "$EndBOARD\n" ) != sizeof("$EndBOARD\n") - 1 ) + goto out; + + rc = true; // wrote all OK + +out: + return rc; +} + + +bool DRAWSEGMENT::Save( FILE* aFile ) const +{ + if( fprintf( aFile, "$DRAWSEGMENT\n" ) != sizeof("$DRAWSEGMENT\n") - 1 ) + return false; + + fprintf( aFile, "Po %d %d %d %d %d %d\n", + m_Shape, + m_Start.x, m_Start.y, + m_End.x, m_End.y, m_Width ); + + if( m_Type != S_CURVE ) + { + fprintf( aFile, "De %d %d %d %lX %X\n", + m_Layer, m_Type, m_Angle, + m_TimeStamp, ReturnStatus() ); + } + else + { + fprintf( aFile, "De %d %d %d %lX %X %d %d %d %d\n", + m_Layer, m_Type, m_Angle, + m_TimeStamp, ReturnStatus(), + m_BezierC1.x,m_BezierC1.y, + m_BezierC2.x,m_BezierC2.y); + } + + if( fprintf( aFile, "$EndDRAWSEGMENT\n" ) != sizeof("$EndDRAWSEGMENT\n") - 1 ) + return false; + + return true; +} + + +/** Note: the old name of class NETINFO_ITEM was EQUIPOT + * so in Save (and read) functions, for compatibility, we use EQUIPOT as + * keyword + */ +bool NETINFO_ITEM::Save( FILE* aFile ) const +{ + bool success = false; + + fprintf( aFile, "$EQUIPOT\n" ); + fprintf( aFile, "Na %d %s\n", GetNet(), EscapedUTF8( m_Netname ).c_str() ); + fprintf( aFile, "St %s\n", "~" ); + + if( fprintf( aFile, "$EndEQUIPOT\n" ) != sizeof("$EndEQUIPOT\n") - 1 ) + goto out; + + success = true; + +out: + return success; +} + + +bool PCB_TARGET::Save( FILE* aFile ) const +{ + bool rc = false; + + if( fprintf( aFile, "$PCB_TARGET\n" ) != sizeof("$PCB_TARGET\n")-1 ) + goto out; + + fprintf( aFile, "Po %X %d %d %d %d %d %8.8lX\n", + m_Shape, m_Layer, + m_Pos.x, m_Pos.y, + m_Size, m_Width, m_TimeStamp ); + + if( fprintf( aFile, "$EndPCB_TARGET\n" ) != sizeof("$EndPCB_TARGET\n")-1 ) + goto out; + + rc = true; + +out: + return rc; +} + + +bool ZONE_CONTAINER::Save( FILE* aFile ) const +{ + unsigned item_pos; + int ret; + unsigned corners_count = m_Poly->corner.size(); + int outline_hatch; + char padoption; + + fprintf( aFile, "$CZONE_OUTLINE\n" ); + + // Save the outline main info + ret = fprintf( aFile, "ZInfo %8.8lX %d %s\n", + m_TimeStamp, m_NetCode, + EscapedUTF8( m_Netname ).c_str() ); + + if( ret < 3 ) + return false; + + // Save the outline layer info + ret = fprintf( aFile, "ZLayer %d\n", m_Layer ); + + if( ret < 1 ) + return false; + + // Save the outline aux info + switch( m_Poly->GetHatchStyle() ) + { + default: + case CPolyLine::NO_HATCH: + outline_hatch = 'N'; + break; + + case CPolyLine::DIAGONAL_EDGE: + outline_hatch = 'E'; + break; + + case CPolyLine::DIAGONAL_FULL: + outline_hatch = 'F'; + break; + } + + ret = fprintf( aFile, "ZAux %d %c\n", corners_count, outline_hatch ); + + if( ret < 2 ) + return false; + + // Save pad option and clearance + switch( m_PadOption ) + { + default: + case PAD_IN_ZONE: + padoption = 'I'; + break; + + case THERMAL_PAD: + padoption = 'T'; + break; + + case PAD_NOT_IN_ZONE: + padoption = 'X'; + break; + } + + ret = fprintf( aFile, "ZClearance %d %c\n", m_ZoneClearance, padoption ); + + if( ret < 2 ) + return false; + + ret = fprintf( aFile, "ZMinThickness %d\n", m_ZoneMinThickness ); + + if( ret < 1 ) + return false; + + ret = fprintf( aFile, + "ZOptions %d %d %c %d %d\n", + m_FillMode, + m_ArcToSegmentsCount, + m_IsFilled ? 'S' : 'F', + m_ThermalReliefGap, + m_ThermalReliefCopperBridge ); + + if( ret < 3 ) + return false; + + ret = fprintf( aFile, + "ZSmoothing %d %d\n", + cornerSmoothingType, cornerRadius ); + + if( ret < 2 ) + return false; + + // Save the corner list + for( item_pos = 0; item_pos < corners_count; item_pos++ ) + { + ret = fprintf( aFile, "ZCorner %d %d %d\n", + m_Poly->corner[item_pos].x, m_Poly->corner[item_pos].y, + m_Poly->corner[item_pos].end_contour ); + + if( ret < 3 ) + return false; + } + + // Save the PolysList + if( m_FilledPolysList.size() ) + { + fprintf( aFile, "$POLYSCORNERS\n" ); + + for( unsigned ii = 0; ii < m_FilledPolysList.size(); ii++ ) + { + const CPolyPt* corner = &m_FilledPolysList[ii]; + ret = fprintf( aFile, + "%d %d %d %d\n", + corner->x, + corner->y, + corner->end_contour, + corner->utility ); + + if( ret < 4 ) + return false; + } + + fprintf( aFile, "$endPOLYSCORNERS\n" ); + } + + // Save the filling segments list + if( m_FillSegmList.size() ) + { + fprintf( aFile, "$FILLSEGMENTS\n" ); + + for( unsigned ii = 0; ii < m_FillSegmList.size(); ii++ ) + { + ret = fprintf( aFile, "%d %d %d %d\n", + m_FillSegmList[ii].m_Start.x, m_FillSegmList[ii].m_Start.y, + m_FillSegmList[ii].m_End.x, m_FillSegmList[ii].m_End.y ); + + if( ret < 4 ) + return false; + } + + fprintf( aFile, "$endFILLSEGMENTS\n" ); + } + + fprintf( aFile, "$endCZONE_OUTLINE\n" ); + + return true; +} + + +bool NETCLASSES::Save( FILE* aFile ) const +{ + bool result; + + // save the default first. + result = m_Default.Save( aFile ); + + if( result ) + { + // the rest will be alphabetical in the *.brd file. + for( const_iterator i = begin(); i!=end(); ++i ) + { + NETCLASS* netclass = i->second; + + result = netclass->Save( aFile ); + if( !result ) + break; + } + } + + return result; +} + + +bool NETCLASS::Save( FILE* aFile ) const +{ + bool result = true; + + fprintf( aFile, "$NCLASS\n" ); + fprintf( aFile, "Name %s\n", EscapedUTF8( m_Name ).c_str() ); + fprintf( aFile, "Desc %s\n", EscapedUTF8( GetDescription() ).c_str() ); + + // Write parameters + + fprintf( aFile, "Clearance %d\n", GetClearance() ); + fprintf( aFile, "TrackWidth %d\n", GetTrackWidth() ); + + fprintf( aFile, "ViaDia %d\n", GetViaDiameter() ); + fprintf( aFile, "ViaDrill %d\n", GetViaDrill() ); + + fprintf( aFile, "uViaDia %d\n", GetuViaDiameter() ); + fprintf( aFile, "uViaDrill %d\n", GetuViaDrill() ); + + // Write members: + for( const_iterator i = begin(); i!=end(); ++i ) + fprintf( aFile, "AddNet %s\n", EscapedUTF8( *i ).c_str() ); + + fprintf( aFile, "$EndNCLASS\n" ); + + return result; +} + + +bool TEXTE_PCB::Save( FILE* aFile ) const +{ + if( m_Text.IsEmpty() ) + return true; + + if( fprintf( aFile, "$TEXTPCB\n" ) != sizeof("$TEXTPCB\n") - 1 ) + return false; + + const char* style = m_Italic ? "Italic" : "Normal"; + + wxArrayString* list = wxStringSplit( m_Text, '\n' ); + + for( unsigned ii = 0; ii < list->Count(); ii++ ) + { + wxString txt = list->Item( ii ); + + if ( ii == 0 ) + fprintf( aFile, "Te %s\n", EscapedUTF8( txt ).c_str() ); + else + fprintf( aFile, "nl %s\n", EscapedUTF8( txt ).c_str() ); + } + + delete list; + + fprintf( aFile, "Po %d %d %d %d %d %d\n", + m_Pos.x, m_Pos.y, m_Size.x, m_Size.y, m_Thickness, m_Orient ); + + char hJustify = 'L'; + switch( m_HJustify ) + { + case GR_TEXT_HJUSTIFY_LEFT: + hJustify = 'L'; + break; + case GR_TEXT_HJUSTIFY_CENTER: + hJustify = 'C'; + break; + case GR_TEXT_HJUSTIFY_RIGHT: + hJustify = 'R'; + break; + default: + hJustify = 'C'; + break; + } + + fprintf( aFile, "De %d %d %lX %s %c\n", m_Layer, + m_Mirror ? 0 : 1, + m_TimeStamp, style, hJustify ); + + if( fprintf( aFile, "$EndTEXTPCB\n" ) != sizeof("$EndTEXTPCB\n") - 1 ) + return false; + + return true; +} + + +/** + * Function Save + * writes the data structures for this object out to a FILE in "*.brd" format. + * @param aFile The FILE to write to. + * @return bool - true if success writing else false. + */ +bool TEXTE_MODULE::Save( FILE* aFile ) const +{ + MODULE* parent = (MODULE*) GetParent(); + int orient = m_Orient; + + // Due to the Pcbnew history, m_Orient is saved in screen value + // but it is handled as relative to its parent footprint + if( parent ) + orient += parent->m_Orient; + + int ret = fprintf( aFile, "T%d %d %d %d %d %d %d %c %c %d %c %s\n", + m_Type, + m_Pos0.x, m_Pos0.y, + m_Size.y, m_Size.x, + orient, + m_Thickness, + m_Mirror ? 'M' : 'N', m_NoShow ? 'I' : 'V', + GetLayer(), + m_Italic ? 'I' : 'N', + EscapedUTF8( m_Text ).c_str() + ); + + return ret > 20; +} + + +bool EDGE_MODULE::Save( FILE* aFile ) const +{ + int ret = -1; + + switch( m_Shape ) + { + case S_SEGMENT: + ret = fprintf( aFile, "DS %d %d %d %d %d %d\n", + m_Start0.x, m_Start0.y, + m_End0.x, m_End0.y, + m_Width, m_Layer ); + break; + + case S_CIRCLE: + ret = fprintf( aFile, "DC %d %d %d %d %d %d\n", + m_Start0.x, m_Start0.y, + m_End0.x, m_End0.y, + m_Width, m_Layer ); + break; + + case S_ARC: + ret = fprintf( aFile, "DA %d %d %d %d %d %d %d\n", + m_Start0.x, m_Start0.y, + m_End0.x, m_End0.y, + m_Angle, + m_Width, m_Layer ); + break; + + case S_POLYGON: + ret = fprintf( aFile, "DP %d %d %d %d %d %d %d\n", + m_Start0.x, m_Start0.y, + m_End0.x, m_End0.y, + (int) m_PolyPoints.size(), + m_Width, m_Layer ); + + for( unsigned i = 0; i 5; +} + + +bool TRACK::Save( FILE* aFile ) const +{ + int type = 0; + + if( Type() == PCB_VIA_T ) + type = 1; + + fprintf( aFile, "Po %d %d %d %d %d %d %d\n", m_Shape, + m_Start.x, m_Start.y, m_End.x, m_End.y, m_Width, m_Drill ); + + fprintf( aFile, "De %d %d %d %lX %X\n", + m_Layer, type, GetNet(), + m_TimeStamp, ReturnStatus() ); + + return true; +} + + +bool DIMENSION::Save( FILE* aFile ) const +{ + bool rc = false; + + // note: COTATION was the previous name of DIMENSION + // this old keyword is used here for compatibility + const char keyWordLine[] = "$COTATION\n"; + const char keyWordLineEnd[] = "$endCOTATION\n"; + + if( fputs( keyWordLine, aFile ) == EOF ) + goto out; + + fprintf( aFile, "Ge %d %d %lX\n", m_Shape, m_Layer, m_TimeStamp ); + + fprintf( aFile, "Va %d\n", m_Value ); + + if( !m_Text->m_Text.IsEmpty() ) + fprintf( aFile, "Te %s\n", EscapedUTF8( m_Text->m_Text ).c_str() ); + else + fprintf( aFile, "Te \"?\"\n" ); + + fprintf( aFile, "Po %d %d %d %d %d %d %d\n", + m_Text->m_Pos.x, m_Text->m_Pos.y, + m_Text->m_Size.x, m_Text->m_Size.y, + m_Text->GetThickness(), m_Text->GetOrientation(), + m_Text->m_Mirror ? 0 : 1 ); + + fprintf( aFile, "Sb %d %d %d %d %d %d\n", S_SEGMENT, + m_crossBarOx, m_crossBarOy, + m_crossBarFx, m_crossBarFy, m_Width ); + + fprintf( aFile, "Sd %d %d %d %d %d %d\n", S_SEGMENT, + m_featureLineDOx, m_featureLineDOy, + m_featureLineDFx, m_featureLineDFy, m_Width ); + + fprintf( aFile, "Sg %d %d %d %d %d %d\n", S_SEGMENT, + m_featureLineGOx, m_featureLineGOy, + m_featureLineGFx, m_featureLineGFy, m_Width ); + + fprintf( aFile, "S1 %d %d %d %d %d %d\n", S_SEGMENT, + m_arrowD1Ox, m_arrowD1Oy, + m_arrowD1Fx, m_arrowD1Fy, m_Width ); + + fprintf( aFile, "S2 %d %d %d %d %d %d\n", S_SEGMENT, + m_arrowD2Ox, m_arrowD2Oy, + m_arrowD2Fx, m_arrowD2Fy, m_Width ); + + + fprintf( aFile, "S3 %d %d %d %d %d %d\n", S_SEGMENT, + m_arrowG1Ox, m_arrowG1Oy, + m_arrowG1Fx, m_arrowG1Fy, m_Width ); + + fprintf( aFile, "S4 %d %d %d %d %d %d\n", S_SEGMENT, + m_arrowG2Ox, m_arrowG2Oy, + m_arrowG2Fx, m_arrowG2Fy, m_Width ); + + if( fputs( keyWordLineEnd, aFile ) == EOF ) + goto out; + + rc = true; + +out: + return rc; +} + + +bool D_PAD::Save( FILE* aFile ) const +{ + int cshape; + const char* texttype; + + // check the return values for first and last fprints() in this function + if( fprintf( aFile, "$PAD\n" ) != sizeof("$PAD\n") - 1 ) + return false; + + switch( m_PadShape ) + { + case PAD_CIRCLE: + cshape = 'C'; break; + + case PAD_RECT: + cshape = 'R'; break; + + case PAD_OVAL: + cshape = 'O'; break; + + case PAD_TRAPEZOID: + cshape = 'T'; break; + + default: + cshape = 'C'; + DisplayError( NULL, _( "Unknown pad shape" ) ); + break; + } + + fprintf( aFile, "Sh \"%.4s\" %c %d %d %d %d %d\n", + m_Padname, cshape, m_Size.x, m_Size.y, + m_DeltaSize.x, m_DeltaSize.y, m_Orient ); + + fprintf( aFile, "Dr %d %d %d", m_Drill.x, m_Offset.x, m_Offset.y ); + + if( m_DrillShape == PAD_OVAL ) + { + fprintf( aFile, " %c %d %d", 'O', m_Drill.x, m_Drill.y ); + } + + fprintf( aFile, "\n" ); + + switch( m_Attribut ) + { + case PAD_STANDARD: + texttype = "STD"; break; + + case PAD_SMD: + texttype = "SMD"; break; + + case PAD_CONN: + texttype = "CONN"; break; + + case PAD_HOLE_NOT_PLATED: + texttype = "HOLE"; break; + + default: + texttype = "STD"; + DisplayError( NULL, wxT( "Invalid Pad attribute" ) ); + break; + } + + fprintf( aFile, "At %s N %8.8X\n", texttype, m_layerMask ); + + fprintf( aFile, "Ne %d %s\n", GetNet(), EscapedUTF8( m_Netname ).c_str() ); + + fprintf( aFile, "Po %d %d\n", m_Pos0.x, m_Pos0.y ); + + if( m_LengthDie != 0 ) + fprintf( aFile, "Le %d\n", m_LengthDie ); + + if( m_LocalSolderMaskMargin != 0 ) + fprintf( aFile, ".SolderMask %d\n", m_LocalSolderMaskMargin ); + + if( m_LocalSolderPasteMargin != 0 ) + fprintf( aFile, ".SolderPaste %d\n", m_LocalSolderPasteMargin ); + + if( m_LocalSolderPasteMarginRatio != 0 ) + fprintf( aFile, ".SolderPasteRatio %g\n", m_LocalSolderPasteMarginRatio ); + + if( m_LocalClearance != 0 ) + fprintf( aFile, ".LocalClearance %d\n", m_LocalClearance ); + + if( fprintf( aFile, "$EndPAD\n" ) != sizeof("$EndPAD\n") - 1 ) + return false; + + return true; +} + + +bool MODULE::Save( FILE* aFile ) const +{ + char statusTxt[8]; + BOARD_ITEM* item; + + bool rc = false; + + fprintf( aFile, "$MODULE %s\n", TO_UTF8( m_LibRef ) ); + + memset( statusTxt, 0, sizeof(statusTxt) ); + if( IsLocked() ) + statusTxt[0] = 'F'; + else + statusTxt[0] = '~'; + + if( m_ModuleStatus & MODULE_is_PLACED ) + statusTxt[1] = 'P'; + else + statusTxt[1] = '~'; + + fprintf( aFile, "Po %d %d %d %d %8.8lX %8.8lX %s\n", + m_Pos.x, m_Pos.y, + m_Orient, m_Layer, m_LastEdit_Time, + m_TimeStamp, statusTxt ); + + fprintf( aFile, "Li %s\n", TO_UTF8( m_LibRef ) ); + + if( !m_Doc.IsEmpty() ) + { + fprintf( aFile, "Cd %s\n", TO_UTF8( m_Doc ) ); + } + + if( !m_KeyWord.IsEmpty() ) + { + fprintf( aFile, "Kw %s\n", TO_UTF8( m_KeyWord ) ); + } + + fprintf( aFile, "Sc %8.8lX\n", m_TimeStamp ); + fprintf( aFile, "AR %s\n", TO_UTF8( m_Path ) ); + fprintf( aFile, "Op %X %X 0\n", m_CntRot90, m_CntRot180 ); + + if( m_LocalSolderMaskMargin != 0 ) + fprintf( aFile, ".SolderMask %d\n", m_LocalSolderMaskMargin ); + + if( m_LocalSolderPasteMargin != 0 ) + fprintf( aFile, ".SolderPaste %d\n", m_LocalSolderPasteMargin ); + + if( m_LocalSolderPasteMarginRatio != 0 ) + fprintf( aFile, ".SolderPasteRatio %g\n", m_LocalSolderPasteMarginRatio ); + + if( m_LocalClearance != 0 ) + fprintf( aFile, ".LocalClearance %d\n", m_LocalClearance ); + + // attributes + if( m_Attributs != MOD_DEFAULT ) + { + fprintf( aFile, "At " ); + + if( m_Attributs & MOD_CMS ) + fprintf( aFile, "SMD " ); + + if( m_Attributs & MOD_VIRTUAL ) + fprintf( aFile, "VIRTUAL " ); + + fprintf( aFile, "\n" ); + } + + // save reference + if( !m_Reference->Save( aFile ) ) + goto out; + + // save value + if( !m_Value->Save( aFile ) ) + goto out; + + // save drawing elements + for( item = m_Drawings; item; item = item->Next() ) + { + switch( item->Type() ) + { + case PCB_MODULE_TEXT_T: + case PCB_MODULE_EDGE_T: + if( !item->Save( aFile ) ) + goto out; + + break; + + default: +#if defined(DEBUG) + printf( "MODULE::Save() ignoring type %d\n", item->Type() ); +#endif + break; + } + } + + // save the pads + for( item = m_Pads; item; item = item->Next() ) + if( !item->Save( aFile ) ) + goto out; + + Write_3D_Descr( aFile ); + + fprintf( aFile, "$EndMODULE %s\n", TO_UTF8( m_LibRef ) ); + + rc = true; +out: + return rc; +} + +/* Save the description of 3D MODULE + */ +int MODULE::Write_3D_Descr( FILE* File ) const +{ + char buf[512]; + + for( S3D_MASTER* t3D = m_3D_Drawings; t3D; t3D = t3D->Next() ) + { + if( !t3D->m_Shape3DName.IsEmpty() ) + { + fprintf( File, "$SHAPE3D\n" ); + + fprintf( File, "Na %s\n", EscapedUTF8( t3D->m_Shape3DName ).c_str() ); + + sprintf( buf, "Sc %lf %lf %lf\n", + t3D->m_MatScale.x, + t3D->m_MatScale.y, + t3D->m_MatScale.z ); + fprintf( File, "%s", to_point( buf ) ); + + sprintf( buf, "Of %lf %lf %lf\n", + t3D->m_MatPosition.x, + t3D->m_MatPosition.y, + t3D->m_MatPosition.z ); + fprintf( File, "%s", to_point( buf ) ); + + sprintf( buf, "Ro %lf %lf %lf\n", + t3D->m_MatRotation.x, + t3D->m_MatRotation.y, + t3D->m_MatRotation.z ); + fprintf( File, "%s", to_point( buf ) ); + + fprintf( File, "$EndSHAPE3D\n" ); + } + } + + return 0; +} + +#endif + diff --git a/pcbnew/kicad_plugin.h b/pcbnew/kicad_plugin.h index ebfd24b974..18ef91e49f 100644 --- a/pcbnew/kicad_plugin.h +++ b/pcbnew/kicad_plugin.h @@ -72,6 +72,7 @@ protected: BOARD* m_board; ///< which BOARD, no ownership here LINE_READER* m_reader; ///< no ownership here. + FILE* m_fp; ///< no ownership here. wxString m_field; ///< reused to stuff MODULE fields. diff --git a/pcbnew/loadcmp.cpp b/pcbnew/loadcmp.cpp index ed08cbcbc2..a65b75033a 100644 --- a/pcbnew/loadcmp.cpp +++ b/pcbnew/loadcmp.cpp @@ -55,20 +55,20 @@ static void DisplayCmpDoc( wxString& Name ); static FOOTPRINT_LIST MList; -bool FOOTPRINT_EDIT_FRAME::Load_Module_From_BOARD( MODULE* Module ) +bool FOOTPRINT_EDIT_FRAME::Load_Module_From_BOARD( MODULE* aModule ) { - MODULE* NewModule; + MODULE* newModule; PCB_BASE_FRAME* parent = (PCB_BASE_FRAME*) GetParent(); - if( Module == NULL ) + if( aModule == NULL ) { if( ! parent->GetBoard() || ! parent->GetBoard()->m_Modules ) return false; - Module = Select_1_Module_From_BOARD( parent->GetBoard() ); + aModule = Select_1_Module_From_BOARD( parent->GetBoard() ); } - if( Module == NULL ) + if( aModule == NULL ) return false; SetCurItem( NULL ); @@ -76,25 +76,25 @@ bool FOOTPRINT_EDIT_FRAME::Load_Module_From_BOARD( MODULE* Module ) Clear_Pcb( false ); GetBoard()->m_Status_Pcb = 0; - NewModule = new MODULE( GetBoard() ); - NewModule->Copy( Module ); - NewModule->m_Link = Module->m_TimeStamp; + newModule = new MODULE( GetBoard() ); + newModule->Copy( aModule ); + newModule->m_Link = aModule->m_TimeStamp; - Module = NewModule; + aModule = newModule; - GetBoard()->Add( Module ); + GetBoard()->Add( aModule ); - Module->m_Flags = 0; + aModule->m_Flags = 0; GetBoard()->m_NetInfo->BuildListOfNets(); GetScreen()->SetCrossHairPosition( wxPoint( 0, 0 ) ); - PlaceModule( Module, NULL ); + PlaceModule( aModule, NULL ); - if( Module->GetLayer() != LAYER_N_FRONT ) - Module->Flip( Module->m_Pos ); + if( aModule->GetLayer() != LAYER_N_FRONT ) + aModule->Flip( aModule->m_Pos ); - Rotate_Module( NULL, Module, 0, false ); + Rotate_Module( NULL, aModule, 0, false ); GetScreen()->ClrModify(); Zoom_Automatique( false ); @@ -104,12 +104,13 @@ bool FOOTPRINT_EDIT_FRAME::Load_Module_From_BOARD( MODULE* Module ) MODULE* PCB_BASE_FRAME::Load_Module_From_Library( const wxString& library, wxDC* DC ) { - MODULE* module; - wxPoint curspos = GetScreen()->GetCrossHairPosition(); - wxString ModuleName, keys; + MODULE* module; + wxPoint curspos = GetScreen()->GetCrossHairPosition(); + wxString moduleName, keys; + bool AllowWildSeach = true; + static wxArrayString HistoryList; static wxString lastCommponentName; - bool AllowWildSeach = true; /* Ask for a component name or key words */ DIALOG_GET_COMPONENT dlg( this, GetComponentDialogPosition(), HistoryList, @@ -120,57 +121,57 @@ MODULE* PCB_BASE_FRAME::Load_Module_From_Library( const wxString& library, wxDC* if( dlg.ShowModal() == wxID_CANCEL ) return NULL; - ModuleName = dlg.GetComponentName(); + moduleName = dlg.GetComponentName(); - if( ModuleName.IsEmpty() ) /* Cancel command */ + if( moduleName.IsEmpty() ) /* Cancel command */ { DrawPanel->MoveCursorToCrossHair(); return NULL; } - ModuleName.MakeUpper(); + moduleName.MakeUpper(); - if( ModuleName[0] == '=' ) // Selection by keywords + if( moduleName[0] == '=' ) // Selection by keywords { AllowWildSeach = false; - keys = ModuleName.AfterFirst( '=' ); - ModuleName = Select_1_Module_From_List( this, library, wxEmptyString, keys ); + keys = moduleName.AfterFirst( '=' ); + moduleName = Select_1_Module_From_List( this, library, wxEmptyString, keys ); - if( ModuleName.IsEmpty() ) /* Cancel command */ + if( moduleName.IsEmpty() ) /* Cancel command */ { DrawPanel->MoveCursorToCrossHair(); return NULL; } } - else if( ( ModuleName.Contains( wxT( "?" ) ) ) - || ( ModuleName.Contains( wxT( "*" ) ) ) ) // Selection wild card + else if( ( moduleName.Contains( wxT( "?" ) ) ) + || ( moduleName.Contains( wxT( "*" ) ) ) ) // Selection wild card { AllowWildSeach = false; - ModuleName = Select_1_Module_From_List( this, library, ModuleName, wxEmptyString ); - if( ModuleName.IsEmpty() ) + moduleName = Select_1_Module_From_List( this, library, moduleName, wxEmptyString ); + if( moduleName.IsEmpty() ) { DrawPanel->MoveCursorToCrossHair(); return NULL; /* Cancel command. */ } } - module = GetModuleLibrary( library, ModuleName, false ); + module = GetModuleLibrary( library, moduleName, false ); if( ( module == NULL ) && AllowWildSeach ) /* Search with wild card */ { AllowWildSeach = false; - wxString wildname = wxChar( '*' ) + ModuleName + wxChar( '*' ); - ModuleName = wildname; - ModuleName = Select_1_Module_From_List( this, library, ModuleName, wxEmptyString ); + wxString wildname = wxChar( '*' ) + moduleName + wxChar( '*' ); + moduleName = wildname; + moduleName = Select_1_Module_From_List( this, library, moduleName, wxEmptyString ); - if( ModuleName.IsEmpty() ) + if( moduleName.IsEmpty() ) { DrawPanel->MoveCursorToCrossHair(); return NULL; /* Cancel command. */ } else { - module = GetModuleLibrary( library, ModuleName, true ); + module = GetModuleLibrary( library, moduleName, true ); } } @@ -179,8 +180,8 @@ MODULE* PCB_BASE_FRAME::Load_Module_From_Library( const wxString& library, wxDC* if( module ) { - lastCommponentName = ModuleName; - AddHistoryComponentName( HistoryList, ModuleName ); + lastCommponentName = moduleName; + AddHistoryComponentName( HistoryList, moduleName ); module->m_Flags = IS_NEW; module->m_Link = 0; @@ -211,14 +212,13 @@ MODULE* PCB_BASE_FRAME::GetModuleLibrary( const wxString& aLibraryFullFilename, bool aDisplayMessageError ) { wxFileName fn; - wxString Name; wxString msg, tmp; - MODULE* NewModule; + MODULE* newModule; FILE* file = NULL; - unsigned ii; + bool one_lib = aLibraryFullFilename.IsEmpty() ? false : true; - for( ii = 0; ii < g_LibraryNames.GetCount(); ii++ ) + for( unsigned ii = 0; ii < g_LibraryNames.GetCount(); ii++ ) { if( one_lib ) fn = aLibraryFullFilename; @@ -266,38 +266,42 @@ MODULE* PCB_BASE_FRAME::GetModuleLibrary( const wxString& aLibraryFullFilename, return NULL; } - /* Reading the list of modules in the library. */ + // Reading the list of modules in the library. curr_lib.ReadSectionIndex(); bool found = curr_lib.FindInList( aModuleName ); - /* Read library. */ + // Read library. if( found ) { + wxString name; + fileReader.Rewind(); while( reader.ReadLine() ) { - char * line = reader.Line(); + char* line = reader.Line(); + StrPurge( line + 8 ); if( strnicmp( line, "$MODULE", 7 ) != 0 ) continue; // Read module name. - Name = FROM_UTF8( line + 8 ); + name = FROM_UTF8( line + 8 ); - if( Name.CmpNoCase( aModuleName ) == 0 ) + if( name.CmpNoCase( aModuleName ) == 0 ) { - NewModule = new MODULE( GetBoard() ); + newModule = new MODULE( GetBoard() ); - // Switch the locale to standard C (needed to print + // Temporarily switch the locale to standard C (needed to print // floating point numbers like 1.3) - SetLocaleTo_C_standard(); - NewModule->ReadDescr( &reader ); - SetLocaleTo_Default(); // revert to the current locale - GetBoard()->Add( NewModule, ADD_APPEND ); + LOCALE_IO toggle; + + newModule->ReadDescr( &reader ); + + GetBoard()->Add( newModule, ADD_APPEND ); SetStatusText( wxEmptyString ); - return NewModule; + return newModule; } } } @@ -405,16 +409,16 @@ static void DisplayCmpDoc( wxString& Name ) MODULE* FOOTPRINT_EDIT_FRAME::Select_1_Module_From_BOARD( BOARD* aPcb ) { - MODULE* Module; + MODULE* module; static wxString OldName; /* Save name of last module selected. */ wxString CmpName, msg; wxArrayString listnames; - Module = aPcb->m_Modules; + module = aPcb->m_Modules; - for( ; Module != NULL; Module = (MODULE*) Module->Next() ) - listnames.Add( Module->m_Reference->m_Text ); + for( ; module != NULL; module = (MODULE*) module->Next() ) + listnames.Add( module->m_Reference->m_Text ); msg.Printf( _( "Modules [%d items]" ), listnames.GetCount() ); @@ -428,13 +432,13 @@ MODULE* FOOTPRINT_EDIT_FRAME::Select_1_Module_From_BOARD( BOARD* aPcb ) OldName = CmpName; - Module = aPcb->m_Modules; + module = aPcb->m_Modules; - for( ; Module != NULL; Module = (MODULE*) Module->Next() ) + for( ; module != NULL; module = (MODULE*) module->Next() ) { - if( CmpName == Module->m_Reference->m_Text ) + if( CmpName == module->m_Reference->m_Text ) break; } - return Module; + return module; }