Commit e7ea0480 authored by Maciej Suminski's avatar Maciej Suminski

Upstream merge.

parents bff37e50 8e6713ca
......@@ -364,13 +364,13 @@ check_find_package_result( OPENGL_FOUND "OpenGL" )
# https://www.mail-archive.com/cmake@cmake.org/msg47501.html
# Handle target used to specify if a target needs wx-widgets or other libraries
# Always defined, empty if no libraries are to be build
# Always defined, empty if no libraries are to be built
add_custom_target( lib-dependencies )
if( KICAD_BUILD_STATIC OR KICAD_BUILD_DYNAMIC )
# This should be build in all cases, if swig exec is not avaiable
# will be impossible also enable SCRIPTING being for PCBNEW required immediatly
# This should be built in all cases, if swig exec is not avaiable
# will be impossible also enable SCRIPTING being for PCBNEW required immediately
include( download_pcre )
include( download_swig )
......
......@@ -172,6 +172,7 @@ set( COMMON_SRCS
eda_dde.cpp
eda_doc.cpp
filter_reader.cpp
# findkicadhelppath.cpp.notused deprecated, use searchhelpfilefullpath.cpp
gestfich.cpp
getrunningmicrosecs.cpp
grid_tricks.cpp
......@@ -189,6 +190,7 @@ set( COMMON_SRCS
ptree.cpp
reporter.cpp
richio.cpp
searchhelpfilefullpath.cpp
search_stack.cpp
selcolor.cpp
systemdirsappend.cpp
......
......@@ -271,6 +271,18 @@ wxConfigBase* EDA_BASE_FRAME::config()
}
const SEARCH_STACK& EDA_BASE_FRAME::sys_search()
{
return Kiface().KifaceSearch();
}
wxString EDA_BASE_FRAME::help_name()
{
return Kiface().GetHelpFileName();
}
void EDA_BASE_FRAME::PrintMsg( const wxString& text )
{
SetStatusText( text );
......@@ -327,33 +339,28 @@ wxString EDA_BASE_FRAME::GetFileFromHistory( int cmdId, const wxString& type,
void EDA_BASE_FRAME::GetKicadHelp( wxCommandEvent& event )
{
wxString msg;
const SEARCH_STACK& search = sys_search();
/* We have to get document for beginners,
* or the the full specific doc
* or the full specific doc
* if event id is wxID_INDEX, we want the document for beginners.
* else the specific doc file (its name is in Kiface().GetHelpFileName())
* The document for beginners is the same for all KiCad utilities
*/
if( event.GetId() == wxID_INDEX )
{
// Temporarily change the help filename
wxString tmp = Kiface().GetHelpFileName();
// Search for "getting_started_in_kicad.pdf" or "Getting_Started_in_KiCad.pdf"
Kiface().SetHelpFileName( wxT( "getting_started_in_kicad.pdf" ) );
wxString helpFile = Kiface().GetHelpFile();
wxString helpFile = SearchHelpFileFullPath( search, wxT( "getting_started_in_kicad.pdf" ) );
if( !helpFile )
{ // Try to find "Getting_Started_in_KiCad.pdf"
Kiface().SetHelpFileName( wxT( "Getting_Started_in_KiCad.pdf" ) );
helpFile = Kiface().GetHelpFile();
}
helpFile = SearchHelpFileFullPath( search, wxT( "Getting_Started_in_KiCad.pdf" ) );
if( !helpFile )
{
msg.Printf( _( "Help file %s could not be found." ),
GetChars( Kiface().GetHelpFileName() ) );
wxString msg = wxString::Format( _(
"Help file '%s' could not be found." ),
wxT( "getting_started_in_kicad.pdf" )
);
wxMessageBox( msg );
}
else
......@@ -361,36 +368,36 @@ void EDA_BASE_FRAME::GetKicadHelp( wxCommandEvent& event )
GetAssociatedDocument( this, helpFile );
}
Kiface().SetHelpFileName( tmp );
return;
}
wxString base_name = help_name();
#if defined ONLINE_HELP_FILES_FORMAT_IS_HTML
if( Kiface().GetHtmlHelpController() == NULL )
{
Kiface().InitOnLineHelp();
}
wxHtmlHelpController* hc = Pgm().GetHtmlHelpController();
wxString helpFile = SearchHelpFileFullPath( search, );
if( Kiface().GetHtmlHelpController() )
if( !!helpFile )
{
Kiface().GetHtmlHelpController()->DisplayContents();
Kiface().GetHtmlHelpController()->Display( Kiface().GetHelpFileName() );
}
else
{
msg.Printf( _( "Help file %s could not be found." ), GetChars( Kiface().GetHelpFileName() ) );
wxMessageBox( msg );
hc->UseConfig( Pgm().CommonSettings() );
hc->SetTitleFormat( wxT( "KiCad Help" ) );
hc->AddBook( helpFile );
}
hc->DisplayContents();
hc->Display( helpFile );
#elif defined ONLINE_HELP_FILES_FORMAT_IS_PDF
wxString helpFile = Kiface().GetHelpFile();
wxString helpFile = SearchHelpFileFullPath( search, base_name );
if( !helpFile )
{
msg.Printf( _( "Help file %s could not be found." ),
GetChars( Kiface().GetHelpFileName() ) );
wxString msg = wxString::Format( _(
"Help file '%s' could not be found." ),
GetChars( base_name )
);
wxMessageBox( msg );
}
else
......
......@@ -64,15 +64,19 @@ bool GetAssociatedDocument( wxFrame* aFrame,
const wxPathList* aPaths)
{
wxString docname, fullfilename, file_ext;
wxString docname, fullfilename;
wxString msg;
wxString command;
bool success = false;
// Is an internet url
static const wxString url_header[3] = { wxT( "http:" ), wxT( "ftp:" ), wxT( "www." ) };
static const wxChar* url_header[3] = {
wxT( "http:" ),
wxT( "ftp:" ),
wxT( "www." )
};
for( int ii = 0; ii < 3; ii++ )
for( unsigned ii = 0; ii < DIM(url_header); ii++ )
{
if( aDocName.First( url_header[ii] ) == 0 ) //. seems an internet url
{
......@@ -133,8 +137,9 @@ bool GetAssociatedDocument( wxFrame* aFrame,
return false;
}
wxFileName CurrentFileName( fullfilename );
file_ext = CurrentFileName.GetExt();
wxFileName currentFileName( fullfilename );
wxString file_ext = currentFileName.GetExt();
if( file_ext == wxT( "pdf" ) )
{
......
#include <fctsys.h>
#include <pgm_base.h>
#include <macros.h>
#include <gestfich.h>
/**
* Function FindKicadHelpPath
* finds the absolute path for KiCad "help" (or "help/&ltlanguage&gt")
* Find path kicad/doc/help/xx/ or kicad/doc/help/:
* from BinDir
* else from environment variable KICAD
* else from one of s_HelpPathList
* typically c:/kicad/doc/help or /usr/share/kicad/help
* or /usr/local/share/kicad/help
* (must have kicad in path name)
*
* xx = iso639-1 language id (2 letters (generic) or 4 letters):
* fr = french (or fr_FR)
* en = English (or en_GB or en_US ...)
* de = deutch
* es = spanish
* pt = portuguese (or pt_BR ...)
*
* default = en (if not found = fr)
*/
wxString FindKicadHelpPath()
{
bool found = false;
wxString bin_dir = Pgm().GetExecutablePath();
if( bin_dir.Last() == '/' )
bin_dir.RemoveLast();
wxString fullPath = bin_dir.BeforeLast( '/' ); // cd ..
fullPath += wxT( "/doc/help/" );
wxString localeString = Pgm().GetLocale()->GetCanonicalName();
wxString path_tmp = fullPath;
#ifdef __WINDOWS__
path_tmp.MakeLower();
#endif
if( path_tmp.Contains( wxT( "kicad" ) ) )
{
if( wxDirExists( fullPath ) )
found = true;
}
// find kicad/help/ from environment variable KICAD
if( !found && Pgm().IsKicadEnvVariableDefined() )
{
fullPath = Pgm().GetKicadEnvVariable() + wxT( "/doc/help/" );
if( wxDirExists( fullPath ) )
found = true;
}
if( !found )
{
// Possibilities online help
const static wxChar* possibilities[] = {
#ifdef __WINDOWS__
wxT( "c:/kicad/doc/help/" ),
wxT( "d:/kicad/doc/help/" ),
wxT( "c:/Program Files/kicad/doc/help/" ),
wxT( "d:/Program Files/kicad/doc/help/" ),
#else
wxT( "/usr/share/doc/kicad/help/" ),
wxT( "/usr/local/share/doc/kicad/help/" ),
wxT( "/usr/local/kicad/doc/help/" ), // default install for "universal
// tarballs" and build for a server
// (new)
wxT( "/usr/local/kicad/help/" ), // default install for "universal
// tarballs" and build for a server
// (old)
#endif
};
for( unsigned i=0; i<DIM(possibilities); ++i )
{
fullPath = possibilities[i];
if( wxDirExists( fullPath ) )
{
found = true;
break;
}
}
}
if( found )
{
wxString langFullPath = fullPath + localeString + UNIX_STRING_DIR_SEP;
if( wxDirExists( langFullPath ) )
return langFullPath;
langFullPath = fullPath + localeString.Left( 2 ) + UNIX_STRING_DIR_SEP;
if( wxDirExists( langFullPath ) )
return langFullPath;
langFullPath = fullPath + wxT( "en/" );
if( wxDirExists( langFullPath ) )
{
return langFullPath;
}
else
{
langFullPath = fullPath + wxT( "fr/" );
if( wxDirExists( langFullPath ) )
return langFullPath;
}
return fullPath;
}
return wxEmptyString;
}
......@@ -622,8 +622,6 @@ const FP_LIB_TABLE::ROW* FP_LIB_TABLE::FindRow( const wxString& aNickname )
// wxGetenv( wchar_t* ) is not re-entrant on linux.
// Put a lock on multithreaded use of wxGetenv( wchar_t* ), called from wxEpandEnvVars(),
// needed by bool ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* aNickname = NULL );
#if 1
#include <ki_mutex.h>
const wxString FP_LIB_TABLE::ExpandSubstitutions( const wxString& aString )
......@@ -637,177 +635,44 @@ const wxString FP_LIB_TABLE::ExpandSubstitutions( const wxString& aString )
return wxExpandEnvVars( aString );
}
#else
const wxString FP_LIB_TABLE::ExpandSubstitutions( const wxString& aString )
{
// We reserve the right to do this another way, by providing our own member
// function.
return wxExpandEnvVars( aString );
}
#endif
bool FP_LIB_TABLE::IsEmpty( bool aIncludeFallback )
{
if( !aIncludeFallback || (fallBack == NULL) )
if( !aIncludeFallback || !fallBack )
return rows.empty();
return fallBack->IsEmpty() && rows.empty();
return rows.empty() && fallBack->IsEmpty( true );
}
bool FP_LIB_TABLE::ConvertFromLegacy( SEARCH_STACK& aSStack, NETLIST& aNetList,
const wxArrayString& aLibNames, REPORTER* aReporter ) throw( IO_ERROR )
MODULE* FP_LIB_TABLE::FootprintLoadWithOptionalNickname( const FPID& aFootprintId )
throw( IO_ERROR, PARSE_ERROR )
{
wxString msg;
FPID lastFPID;
COMPONENT* component;
MODULE* module = 0;
bool retv = true;
if( aNetList.IsEmpty() )
return true;
aNetList.SortByFPID();
wxString libPath;
PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::LEGACY ) );
wxString nickname = aFootprintId.GetLibNickname();
wxString fpname = aFootprintId.GetFootprintName();
for( unsigned ii = 0; ii < aNetList.GetCount(); ii++ )
if( nickname.size() )
{
component = aNetList.GetComponent( ii );
// The footprint hasn't been assigned yet so ignore it.
if( component->GetFPID().empty() )
continue;
if( component->GetFPID() != lastFPID )
{
module = NULL;
for( unsigned ii = 0; ii < aLibNames.GetCount(); ii++ )
{
wxFileName fn( wxEmptyString, aLibNames[ii], LegacyFootprintLibPathExtension );
libPath = aSStack.FindValidPath( fn );
if( !libPath )
{
if( aReporter )
{
msg.Printf( _( "Cannot find footprint library file '%s' in any of the "
"KiCad legacy library search paths.\n" ),
GetChars( fn.GetFullPath() ) );
aReporter->Report( msg );
}
retv = false;
continue;
}
module = pi->FootprintLoad( libPath, component->GetFPID().GetFootprintName() );
return FootprintLoad( nickname, fpname );
}
if( module )
{
lastFPID = component->GetFPID();
break;
}
}
}
// nickname is empty, sequentially search (alphabetically) all libs/nicks for first match:
else
{
std::vector<wxString> nicks = GetLogicalLibs();
if( !module )
// Search each library going through libraries alphabetically.
for( unsigned i = 0; i<nicks.size(); ++i )
{
if( aReporter )
{
msg.Printf( _( "Component `%s` footprint '%s' was not found in any legacy "
"library.\n" ),
GetChars( component->GetReference() ),
GetChars( component->GetFPID().Format() ) );
aReporter->Report( msg );
}
// Clear the footprint assignment since the old library lookup method is no
// longer valid.
FPID emptyFPID;
component->SetFPID( emptyFPID );
retv = false;
continue;
// FootprintLoad() returns NULL on not found, does not throw exception
// unless there's an IO_ERROR.
MODULE* ret = FootprintLoad( nicks[i], fpname );
if( ret )
return ret;
}
else
{
wxString libNickname;
FP_LIB_TABLE* cur = this;
do
{
cur->ensureIndex();
for( unsigned i = 0; i < cur->rows.size(); i++ )
{
wxString uri = cur->rows[i].GetFullURI( true );
if( wxFileName::GetPathSeparator() == wxChar( '\\' )
&& uri.Find( wxChar( '/' ) ) >= 0 )
{
uri.Replace( wxT( "/"), wxT( "\\" ) );
}
#ifdef __WINDOWS__
if( uri.CmpNoCase( libPath ) )
#else
if( uri == libPath )
#endif
{
libNickname = cur->rows[i].GetNickName();
break;
}
}
} while( ( cur = cur->fallBack ) != 0 && libNickname.IsEmpty() );
if( libNickname.IsEmpty() )
{
if( aReporter )
{
msg.Printf( _( "Component '%s' footprint '%s' legacy library path '%s' "
"was not found in the footprint library table.\n" ),
GetChars( component->GetReference() ),
GetChars( component->GetFPID().Format() ) );
aReporter->Report( msg );
}
retv = false;
}
else
{
FPID newFPID = lastFPID;
newFPID.SetLibNickname( libNickname );
if( !newFPID.IsValid() )
{
if( aReporter )
{
msg.Printf( _( "Component '%s' FPID '%s' is not valid.\n" ),
GetChars( component->GetReference() ),
GetChars( newFPID.Format() ) );
aReporter->Report( msg );
}
retv = false;
}
else
{
// The footprint name should already be set.
component->SetFPID( newFPID );
}
}
}
return NULL;
}
return retv;
}
......@@ -839,17 +704,14 @@ bool FP_LIB_TABLE::LoadGlobalTable( FP_LIB_TABLE& aTable ) throw (IO_ERROR, PARS
// The fallback is to create an empty global footprint table for the user to populate.
if( fileName.IsEmpty() || !::wxCopyFile( fileName, fn.GetFullPath(), false ) )
{
FP_LIB_TABLE emptyTable;
FILE_OUTPUTFORMATTER sf( fn.GetFullPath() );
FP_LIB_TABLE emptyTable;
emptyTable.Format( &sf, 0 );
emptyTable.Save( fn.GetFullPath() );
}
}
FILE_LINE_READER reader( fn.GetFullPath() );
FP_LIB_TABLE_LEXER lexer( &reader );
aTable.Load( fn.GetFullPath() );
aTable.Parse( &lexer );
return tableExists;
}
......
......@@ -78,66 +78,6 @@
* like export KICAD=/my_path/kicad if /my_path/kicad is not a default path
*/
// Path list for online help
static wxString s_HelpPathList[] = {
#ifdef __WINDOWS__
wxT( "c:/kicad/doc/help/" ),
wxT( "d:/kicad/doc/help/" ),
wxT( "c:/Program Files/kicad/doc/help/" ),
wxT( "d:/Program Files/kicad/doc/help/" ),
#else
wxT( "/usr/share/doc/kicad/help/" ),
wxT( "/usr/local/share/doc/kicad/help/" ),
wxT( "/usr/local/kicad/doc/help/" ), // default install for "universal
// tarballs" and build for a server
// (new)
wxT( "/usr/local/kicad/help/" ), // default install for "universal
// tarballs" and build for a server
// (old)
#endif
wxT( "end_list" ) // End of list symbol, do not change
};
// Path list for KiCad data files
static wxString s_KicadDataPathList[] = {
#ifdef __WINDOWS__
wxT( "c:/kicad/share/" ),
wxT( "d:/kicad/share/" ),
wxT( "c:/kicad/" ),
wxT( "d:/kicad/" ),
wxT( "c:/Program Files/kicad/share/" ),
wxT( "d:/Program Files/kicad/share/" ),
wxT( "c:/Program Files/kicad/" ),
wxT( "d:/Program Files/kicad/" ),
#else
wxT( "/usr/share/kicad/" ),
wxT( "/usr/local/share/kicad/" ),
wxT( "/usr/local/kicad/share/" ), // default data path for "universal
// tarballs" and build for a server
// (new)
wxT( "/usr/local/kicad/" ), // default data path for "universal
// tarballs" and build for a server
// (old)
#endif
wxT( "end_list" ) // End of list symbol, do not change
};
// Path list for KiCad binary files
static wxString s_KicadBinaryPathList[] = {
#ifdef __WINDOWS__
wxT( "c:/kicad/bin/" ),
wxT( "d:/kicad/bin/" ),
wxT( "c:/Program Files/kicad/bin/" ),
wxT( "d:/Program Files/kicad/bin/" ),
#else
wxT( "/usr/bin/" ),
wxT( "/usr/local/bin/" ),
wxT( "/usr/local/kicad/bin/" ),
#endif
wxT( "end_list" ) // End of list symbol, do not change
};
wxString MakeReducedFileName( const wxString& fullfilename,
const wxString& default_path,
......@@ -281,7 +221,7 @@ wxString EDA_FileSelector( const wxString& Title,
defaultname,
dotted_Ext,
Mask,
flag, /* open mode wxFD_OPEN, wxFD_SAVE .. */
flag, // open mode wxFD_OPEN, wxFD_SAVE ..
Frame,
Pos.x, Pos.y );
......@@ -292,123 +232,48 @@ wxString EDA_FileSelector( const wxString& Title,
}
wxString FindKicadHelpPath()
{
wxString FullPath, LangFullPath, tmp;
wxString LocaleString;
bool PathFound = false;
/* find kicad/help/ */
tmp = Pgm().GetExecutablePath();
if( tmp.Last() == '/' )
tmp.RemoveLast();
FullPath = tmp.BeforeLast( '/' ); // cd ..
FullPath += wxT( "/doc/help/" );
LocaleString = Pgm().GetLocale()->GetCanonicalName();
wxString path_tmp = FullPath;
#ifdef __WINDOWS__
path_tmp.MakeLower();
#endif
if( path_tmp.Contains( wxT( "kicad" ) ) )
{
if( wxDirExists( FullPath ) )
PathFound = true;
}
/* find kicad/help/ from environment variable KICAD */
if( !PathFound && Pgm().IsKicadEnvVariableDefined() )
{
FullPath = Pgm().GetKicadEnvVariable() + wxT( "/doc/help/" );
if( wxDirExists( FullPath ) )
PathFound = true;
}
/* find kicad/help/ from "s_HelpPathList" */
int ii = 0;
while( !PathFound )
{
FullPath = s_HelpPathList[ii++];
if( FullPath == wxT( "end_list" ) )
break;
if( wxDirExists( FullPath ) )
PathFound = true;
}
if( PathFound )
{
LangFullPath = FullPath + LocaleString + UNIX_STRING_DIR_SEP;
if( wxDirExists( LangFullPath ) )
return LangFullPath;
LangFullPath = FullPath + LocaleString.Left( 2 ) + UNIX_STRING_DIR_SEP;
if( wxDirExists( LangFullPath ) )
return LangFullPath;
LangFullPath = FullPath + wxT( "en/" );
if( wxDirExists( LangFullPath ) )
{
return LangFullPath;
}
else
{
LangFullPath = FullPath + wxT( "fr/" );
if( wxDirExists( LangFullPath ) )
return LangFullPath;
}
return FullPath;
}
return wxEmptyString;
}
wxString FindKicadFile( const wxString& shortname )
{
wxString FullFileName;
/* Test the presence of the file in the directory shortname of
* the KiCad binary path.
*/
FullFileName = Pgm().GetExecutablePath() + shortname;
// Test the presence of the file in the directory shortname of
// the KiCad binary path.
wxString fullFileName = Pgm().GetExecutablePath() + shortname;
if( wxFileExists( FullFileName ) )
return FullFileName;
if( wxFileExists( fullFileName ) )
return fullFileName;
/* Test the presence of the file in the directory shortname
* defined by the environment variable KiCad.
*/
// Test the presence of the file in the directory shortname
// defined by the environment variable KiCad.
if( Pgm().IsKicadEnvVariableDefined() )
{
FullFileName = Pgm().GetKicadEnvVariable() + shortname;
fullFileName = Pgm().GetKicadEnvVariable() + shortname;
if( wxFileExists( FullFileName ) )
return FullFileName;
if( wxFileExists( fullFileName ) )
return fullFileName;
}
/* find binary file from default path list:
* /usr/local/kicad/linux or c:/kicad/winexe
* (see s_KicadDataPathList) */
int ii = 0;
// find binary file from possibilities list:
// /usr/local/kicad/linux or c:/kicad/winexe
while( 1 )
{
if( s_KicadBinaryPathList[ii] == wxT( "end_list" ) )
break;
// Path list for KiCad binary files
const static wxChar* possibilities[] = {
#ifdef __WINDOWS__
wxT( "c:/kicad/bin/" ),
wxT( "d:/kicad/bin/" ),
wxT( "c:/Program Files/kicad/bin/" ),
wxT( "d:/Program Files/kicad/bin/" ),
#else
wxT( "/usr/bin/" ),
wxT( "/usr/local/bin/" ),
wxT( "/usr/local/kicad/bin/" ),
#endif
};
FullFileName = s_KicadBinaryPathList[ii++] + shortname;
for( unsigned i=0; i<DIM(possibilities); ++i )
{
fullFileName = possibilities[i] + shortname;
if( wxFileExists( FullFileName ) )
return FullFileName;
if( wxFileExists( fullFileName ) )
return fullFileName;
}
return shortname;
......@@ -418,13 +283,13 @@ wxString FindKicadFile( const wxString& shortname )
int ExecuteFile( wxWindow* frame, const wxString& ExecFile, const wxString& param,
wxProcess *callback )
{
wxString FullFileName;
wxString fullFileName;
FullFileName = FindKicadFile( ExecFile );
fullFileName = FindKicadFile( ExecFile );
#ifdef __WXMAC__
if( wxFileExists( FullFileName ) || wxDir::Exists( FullFileName ) )
if( wxFileExists( fullFileName ) || wxDir::Exists( fullFileName ) )
{
return ProcessExecute( Pgm().GetExecutablePath() + wxT( "/" )
+ ExecFile + wxT( " " )
......@@ -435,16 +300,16 @@ int ExecuteFile( wxWindow* frame, const wxString& ExecFile, const wxString& para
return ProcessExecute( wxT( "/usr/bin/open " ) + param, wxEXEC_ASYNC, callback );
}
#else
if( wxFileExists( FullFileName ) )
if( wxFileExists( fullFileName ) )
{
if( !param.IsEmpty() )
FullFileName += wxT( " " ) + param;
fullFileName += wxT( " " ) + param;
return ProcessExecute( FullFileName, wxEXEC_ASYNC, callback );
return ProcessExecute( fullFileName, wxEXEC_ASYNC, callback );
}
#endif
wxString msg;
msg.Printf( _( "Command <%s> could not found" ), GetChars( FullFileName ) );
msg.Printf( _( "Command <%s> could not found" ), GetChars( fullFileName ) );
DisplayError( frame, msg, 20 );
return -1;
}
......@@ -452,13 +317,13 @@ int ExecuteFile( wxWindow* frame, const wxString& ExecFile, const wxString& para
wxString KicadDatasPath()
{
bool PathFound = false;
bool found = false;
wxString data_path;
if( Pgm().IsKicadEnvVariableDefined() ) // Path defined by the KICAD environment variable.
{
data_path = Pgm().GetKicadEnvVariable();
PathFound = true;
found = true;
}
else // Path of executables.
{
......@@ -485,33 +350,56 @@ wxString KicadDatasPath()
if( wxDirExists( data_path ) )
{
PathFound = true;
found = true;
}
else if( wxDirExists( old_path ) )
{
data_path = old_path;
PathFound = true;
found = true;
}
}
}
/* find KiCad from default path list:
* /usr/local/kicad/ or c:/kicad/
* (see s_KicadDataPathList) */
int ii = 0;
while( !PathFound )
if( !found )
{
if( s_KicadDataPathList[ii] == wxT( "end_list" ) )
break;
// find KiCad from possibilities list:
// /usr/local/kicad/ or c:/kicad/
data_path = s_KicadDataPathList[ii++];
const static wxChar* possibilities[] = {
#ifdef __WINDOWS__
wxT( "c:/kicad/share/" ),
wxT( "d:/kicad/share/" ),
wxT( "c:/kicad/" ),
wxT( "d:/kicad/" ),
wxT( "c:/Program Files/kicad/share/" ),
wxT( "d:/Program Files/kicad/share/" ),
wxT( "c:/Program Files/kicad/" ),
wxT( "d:/Program Files/kicad/" ),
#else
wxT( "/usr/share/kicad/" ),
wxT( "/usr/local/share/kicad/" ),
wxT( "/usr/local/kicad/share/" ), // default data path for "universal
// tarballs" and build for a server
// (new)
wxT( "/usr/local/kicad/" ), // default data path for "universal
// tarballs" and build for a server
// (old)
#endif
};
for( unsigned i=0; i<DIM(possibilities); ++i )
{
data_path = possibilities[i];
if( wxDirExists( data_path ) )
PathFound = true;
if( wxDirExists( data_path ) )
{
found = true;
break;
}
}
}
if( PathFound )
if( found )
{
data_path.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
......@@ -569,38 +457,36 @@ bool OpenPDF( const wxString& file )
}
success = false;
command.Empty();
command.clear();
if( !success )
{
#ifndef __WINDOWS__
#if !defined(__WINDOWS__)
AddDelimiterString( filename );
/* here is a list of PDF viewers candidates */
const static wxString tries[] =
// here is a list of PDF viewers candidates
static const wxChar* tries[] =
{
wxT( "/usr/bin/evince" ),
wxT( "/usr/bin/okular" ),
wxT( "/usr/bin/gpdf" ),
wxT( "/usr/bin/konqueror" ),
wxT( "/usr/bin/kpdf" ),
wxT( "/usr/bin/xpdf" ),
wxT( "/usr/bin/open" ), // BSD and OSX file & dir opener
wxT( "/usr/bin/xdg-open" ), // Freedesktop file & dir opener
wxT( "" ),
};
for( int ii = 0; ; ii++ )
for( unsigned ii = 0; ii<DIM(tries); ii++ )
{
if( tries[ii].IsEmpty() )
break;
if( wxFileExists( tries[ii] ) )
{
command = tries[ii] + wxT( " " ) + filename;
command = tries[ii];
command += wxT( ' ' );
command += filename;
break;
}
}
#endif
}
}
......
......@@ -55,10 +55,11 @@ static void setSearchPaths( SEARCH_STACK* aDst, KIWAY::FACE_T aId )
// we must add <kicad path>/library and <kicad path>/library/doc
if( aId == KIWAY::FACE_SCH )
{
// Add schematic doc file path (library/doc) to search path list.
fn.AppendDir( wxT( "library" ) );
aDst->AddPaths( fn.GetPath() );
// Add schematic doc file path (library/doc)to search path list.
fn.AppendDir( wxT( "doc" ) );
aDst->AddPaths( fn.GetPath() );
......@@ -85,8 +86,10 @@ static void setSearchPaths( SEARCH_STACK* aDst, KIWAY::FACE_T aId )
aDst->AddPaths( fn.GetPath() );
}
aDst->AddPaths( wxT( "/usr/local/share" ) );
#if 1 && defined(DEBUG)
aDst->Show( "kiway" );
aDst->Show( "kiface" );
#endif
}
......@@ -121,86 +124,3 @@ void KIFACE_I::end_common()
m_bm.End();
}
wxString KIFACE_I::GetHelpFile()
{
wxString fn;
wxArrayString subdirs;
wxArrayString altsubdirs;
// FIXME: This is not the ideal way to handle this. Unfortunately, the
// CMake install paths seem to be a moving target so this crude
// hack solves the problem of install path differences between
// Windows and non-Windows platforms.
// Partially fixed, but must be enhanced
// Create subdir tree for "standard" linux distributions, when KiCad comes
// from a distribution files are in /usr/share/doc/kicad/help and binaries
// in /usr/bin or /usr/local/bin
subdirs.Add( wxT( "share" ) );
subdirs.Add( wxT( "doc" ) );
subdirs.Add( wxT( "kicad" ) );
subdirs.Add( wxT( "help" ) );
// Create subdir tree for linux and Windows KiCad pack.
// Note the pack form under linux is also useful if a user wants to
// install KiCad to a server because there is only one path to mount
// or export (something like /usr/local/kicad).
// files are in <install dir>/kicad/doc/help
// (often /usr/local/kicad/kicad/doc/help)
// <install dir>/kicad/ is retrieved from m_BinDir
altsubdirs.Add( wxT( "doc" ) );
altsubdirs.Add( wxT( "help" ) );
/* Search for a help file.
* we *must* find a help file.
* so help is searched in directories in this order:
* help/<canonical name> like help/en_GB
* help/<short name> like help/en
* help/en
*/
wxLocale* i18n = Pgm().GetLocale();
// Step 1 : Try to find help file in help/<canonical name>
subdirs.Add( i18n->GetCanonicalName() );
altsubdirs.Add( i18n->GetCanonicalName() );
fn = m_bm.m_search.FindFileInSearchPaths( m_bm.m_help_file, &altsubdirs );
if( !fn )
fn = m_bm.m_search.FindFileInSearchPaths( m_bm.m_help_file, &subdirs );
// Step 2 : if not found Try to find help file in help/<short name>
if( !fn )
{
subdirs.RemoveAt( subdirs.GetCount() - 1 );
altsubdirs.RemoveAt( altsubdirs.GetCount() - 1 );
// wxLocale::GetName() does not return always the short name
subdirs.Add( i18n->GetName().BeforeLast( '_' ) );
altsubdirs.Add( i18n->GetName().BeforeLast( '_' ) );
fn = m_bm.m_search.FindFileInSearchPaths( m_bm.m_help_file, &altsubdirs );
if( !fn )
fn = m_bm.m_search.FindFileInSearchPaths( m_bm.m_help_file, &subdirs );
}
// Step 3 : if not found Try to find help file in help/en
if( !fn )
{
subdirs.RemoveAt( subdirs.GetCount() - 1 );
altsubdirs.RemoveAt( altsubdirs.GetCount() - 1 );
subdirs.Add( wxT( "en" ) );
altsubdirs.Add( wxT( "en" ) );
fn = m_bm.m_search.FindFileInSearchPaths( m_bm.m_help_file, &altsubdirs );
if( !fn )
fn = m_bm.m_search.FindFileInSearchPaths( m_bm.m_help_file, &subdirs );
}
return fn;
}
......@@ -744,7 +744,7 @@ void WORKSHEET_LAYOUT::SetDefaultLayout()
{
lp_parser.Parse( this );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
wxLogMessage( ioe.errorText );
}
......@@ -765,7 +765,7 @@ void WORKSHEET_LAYOUT::SetPageLayout( const char* aPageLayout, bool Append )
{
lp_parser.Parse( this );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
wxLogMessage( ioe.errorText );
}
......@@ -828,7 +828,7 @@ void WORKSHEET_LAYOUT::SetPageLayout( const wxString& aFullFileName, bool Append
{
lp_parser.Parse( this );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
wxLogMessage( ioe.errorText );
}
......
......@@ -297,6 +297,13 @@ void PGM_BASE::destroy()
delete m_locale;
m_locale = 0;
/*
// Close the help frame
if( m_html_ctrl && m_html_ctrl->GetFrame() ) // returns NULL if no help frame active
m_html_ctrl->GetFrame()->Close( true );
}
*/
delete m_html_ctrl;
m_html_ctrl = 0;
}
......@@ -415,30 +422,18 @@ bool PGM_BASE::initPgm()
}
void PGM_BASE::SetHtmlHelpController( wxHtmlHelpController* aController )
void PGM_BASE::initHtmlHelpController()
{
delete m_html_ctrl;
m_html_ctrl = aController;
}
void PGM_BASE::InitOnLineHelp()
{
wxString fullfilename = FindKicadHelpPath();
#if defined ONLINE_HELP_FILES_FORMAT_IS_HTML
m_HelpFileName = fullfilename + wxT( ".html" );
fullfilename += wxT( "kicad.hhp" );
if( wxFileExists( fullfilename ) )
{
m_html_ctrl = new wxHtmlHelpController( wxHF_TOOLBAR | wxHF_CONTENTS |
wxHF_PRINT | wxHF_OPEN_FILES
/*| wxHF_SEARCH */ );
m_html_ctrl->UseConfig( m_common_settings );
m_html_ctrl->SetTitleFormat( wxT( "KiCad Help" ) );
m_html_ctrl->AddBook( fullfilename );
}
if( !m_html_ctrl )
m_html_ctrl = new wxHtmlHelpController(
wxHF_TOOLBAR | wxHF_CONTENTS |
wxHF_PRINT | wxHF_OPEN_FILES
// | wxHF_SEARCH
);
wxASSERT( m_html_ctrl ); // may not leave here as NULL
#elif defined ONLINE_HELP_FILES_FORMAT_IS_PDF
m_html_ctrl = NULL;
......@@ -449,10 +444,22 @@ void PGM_BASE::InitOnLineHelp()
}
wxHtmlHelpController* PGM_BASE::HtmlHelpController()
{
if( !m_html_ctrl )
initHtmlHelpController();
// there should not be calls to this unless ONLINE_HELP_FILES_FORMAT_IS_HTML is defined
wxASSERT( m_html_ctrl );
return m_html_ctrl;
}
bool PGM_BASE::setExecutablePath()
{
// Apple MacOSx
#ifdef __APPLE__
#ifdef __APPLE__ // Apple MacOSx
// Derive path from location of the app bundle
CFBundleRef mainBundle = CFBundleGetMainBundle();
......
......@@ -23,18 +23,19 @@
*/
#include <wx/stdpaths.h>
#include <fctsys.h>
#include <macros.h>
#include <gr_basic.h>
#include <pgm_base.h>
#include <project.h>
#include <wx/stdpaths.h>
#include <confirm.h>
#include <kicad_string.h>
#include <config_params.h>
#include <wildcards_and_files_ext.h>
PROJECT::PROJECT()
{
memset( m_elems, 0, sizeof(m_elems) );
......@@ -198,18 +199,18 @@ wxConfigBase* PROJECT::configCreate( const SEARCH_STACK& aSList, const wxString&
const wxString& aGroupName, bool aForceUseLocalConfig )
{
wxConfigBase* cfg = 0;
wxFileName fn = aFileName;
wxFileName fn = aFileName;
fn.SetExt( ProjectFileExtension );
wxString cur_pro_fn = fn.GetFullPath();
// is there an edge transition, a change in m_project_filename?
if( m_project_name != fn )
if( m_project_name != cur_pro_fn )
{
m_sch_search.Clear();
SetProjectFullName( fn.GetFullPath() );
// to the empty list, add project dir as first
// to the empty lists, add project dir as first
m_sch_search.AddPaths( fn.GetPath() );
// append all paths from aSList
......@@ -228,8 +229,6 @@ wxConfigBase* PROJECT::configCreate( const SEARCH_STACK& aSList, const wxString&
// Init local config filename
if( aForceUseLocalConfig || fn.FileExists() )
{
wxString cur_pro_fn = fn.GetFullPath();
cfg = new wxFileConfig( wxEmptyString, wxEmptyString, cur_pro_fn, wxEmptyString );
cfg->DontCreateOnDemand();
......@@ -262,31 +261,43 @@ wxConfigBase* PROJECT::configCreate( const SEARCH_STACK& aSList, const wxString&
}
else // Version incorrect
{
wxLogDebug( wxT( "Project file version is zero, not using this old project file, going with template." ) );
delete cfg;
cfg = 0;
}
}
// Search for the template kicad.pro file by using caller's SEARCH_STACK.
// No suitable pro file was found, either does not exist, or is too old.
// Use the template kicad.pro file. Find it by using caller's SEARCH_STACK.
wxString kicad_pro_template = aSList.FindValidPath( wxT( "kicad.pro" ) );
if( !kicad_pro_template )
{
wxLogDebug( wxT( "Template file <kicad.pro> not found." ) );
wxLogDebug( wxT( "Template file <kicad.pro> not found using search paths." ) );
fn = wxFileName( wxStandardPaths::Get().GetDocumentsDir(),
wxT( "kicad" ), ProjectFileExtension );
}
else
{
fn = kicad_pro_template;
wxFileName templ( wxStandardPaths::Get().GetDocumentsDir(),
wxT( "kicad" ), ProjectFileExtension );
if( !templ.IsFileReadable() )
{
wxString msg = wxString::Format( _( "Unable to find kicad.pro template file." ) );
DisplayError( NULL, msg );
return NULL;
}
kicad_pro_template = templ.GetFullPath();
}
cfg = new wxFileConfig( wxEmptyString, wxEmptyString, wxEmptyString, fn.GetFullPath() );
// copy the template to cur_pro_fn, and open it at that destination.
wxCopyFile( kicad_pro_template, cur_pro_fn );
cfg = new wxFileConfig( wxEmptyString, wxEmptyString, cur_pro_fn, wxEmptyString );
cfg->DontCreateOnDemand();
SetProjectFullName( fn.GetFullPath() );
SetProjectFullName( cur_pro_fn );
return cfg;
}
......@@ -296,6 +307,12 @@ void PROJECT::ConfigSave( const SEARCH_STACK& aSList, const wxString& aFileName
{
std::auto_ptr<wxConfigBase> cfg( configCreate( aSList, aFileName, aGroupName, FORCE_LOCAL_CONFIG ) );
if( !cfg.get() )
{
// could not find template
return;
}
cfg->SetPath( wxCONFIG_PATH_SEPARATOR );
cfg->Write( wxT( "update" ), DateAndTime() );
......@@ -326,6 +343,12 @@ bool PROJECT::ConfigLoad( const SEARCH_STACK& aSList, const wxString& aFileName,
{
std::auto_ptr<wxConfigBase> cfg( configCreate( aSList, aFileName, aGroupName, false ) );
if( !cfg.get() )
{
// could not find template
return false;
}
cfg->SetPath( wxCONFIG_PATH_SEPARATOR );
wxString timestamp = cfg->Read( wxT( "update" ) );
......
......@@ -104,31 +104,6 @@ void SEARCH_STACK::AddPaths( const wxString& aPaths, int aIndex )
}
wxString SEARCH_STACK::FindFileInSearchPaths(
const wxString& aFilename, const wxArrayString* aSubdirs )
{
wxPathList paths;
for( unsigned i = 0; i < GetCount(); ++i )
{
wxFileName fn( (*this)[i] );
if( aSubdirs )
{
for( unsigned j = 0; j < aSubdirs->GetCount(); j++ )
fn.AppendDir( (*aSubdirs)[j] );
}
if( fn.DirExists() )
{
paths.Add( fn.GetPath() );
}
}
return paths.FindValidPath( aFilename );
}
void RETAINED_PATH::Clear()
{
m_retained_path.Clear();
......
#include <pgm_base.h>
#include <common.h>
/**
* Function FindFileInSearchPaths
* looks in "this" for \a aFilename, but first modifies every search
* path by appending a list of path fragments from aSubdirs. That modification
* is not rentative.
*/
wxString FindFileInSearchPaths( const SEARCH_STACK& aStack,
const wxString& aFilename, const wxArrayString* aSubdirs )
{
wxPathList paths;
for( unsigned i = 0; i < aStack.GetCount(); ++i )
{
wxFileName fn( aStack[i], wxEmptyString );
if( aSubdirs )
{
for( unsigned j = 0; j < aSubdirs->GetCount(); j++ )
fn.AppendDir( (*aSubdirs)[j] );
}
if( fn.DirExists() )
{
paths.Add( fn.GetPath() );
}
}
return paths.FindValidPath( aFilename );
}
// See also FindKicadHelpPath.cpp.notused.
wxString SearchHelpFileFullPath( const SEARCH_STACK& aSStack, const wxString& aBaseName )
{
wxArrayString subdirs;
wxArrayString altsubdirs;
SEARCH_STACK ss = aSStack;
// It might already be in aSStack, but why depend on other code
// far away when it's so easy to add it again (to our copy) as the first place to look.
// This is CMAKE_INSTALL_PREFIX:
ss.AddPaths( wxT( DEFAULT_INSTALL_PATH ), 0 );
// If there's a KICAD environment variable set, use that guy's path also
ss.AddPaths( Pgm().GetKicadEnvVariable(), 0 );
#if 1 // && defined(__linux__)
// Based on kicad-doc.bzr/CMakeLists.txt, line 20, the help files are
// installed into "<CMAKE_INSTALL_PREFIX>/share/doc/kicad/help" for linux.
// This is ${KICAD_HELP} var in that CMakeLists.txt file.
// Below we account for an international subdirectory.
subdirs.Add( wxT( "share" ) );
subdirs.Add( wxT( "doc" ) );
subdirs.Add( wxT( "kicad" ) );
subdirs.Add( wxT( "help" ) );
#endif
#if 1 // && defined(__WINDOWS__)
// Based on kicad-doc.bzr/CMakeLists.txt, line 35, the help files are
// installed into "<CMAKE_INSTALL_PREFIX>/doc/help" for Windows.
// This is ${KICAD_HELP} var in that CMakeLists.txt file.
// Below we account for an international subdirectory.
altsubdirs.Add( wxT( "doc" ) );
altsubdirs.Add( wxT( "help" ) );
#endif
/* Search for a help file.
* we *must* find a help file.
* so help is searched in directories in this order:
* help/<canonical name> like help/en_GB
* help/<short name> like help/en
* help/en
*/
wxLocale* i18n = Pgm().GetLocale();
// Step 1 : Try to find help file in help/<canonical name>
subdirs.Add( i18n->GetCanonicalName() );
altsubdirs.Add( i18n->GetCanonicalName() );
#if defined(DEBUG) && 0
ss.Show( __func__ );
printf( "%s: m_help_file:'%s'\n", __func__, TO_UTF8( aBaseName ) );
#endif
wxString fn = FindFileInSearchPaths( ss, aBaseName, &altsubdirs );
if( !fn )
fn = FindFileInSearchPaths( ss, aBaseName, &subdirs );
// Step 2 : if not found Try to find help file in help/<short name>
if( !fn )
{
subdirs.RemoveAt( subdirs.GetCount() - 1 );
altsubdirs.RemoveAt( altsubdirs.GetCount() - 1 );
// wxLocale::GetName() does not return always the short name
subdirs.Add( i18n->GetName().BeforeLast( '_' ) );
altsubdirs.Add( i18n->GetName().BeforeLast( '_' ) );
fn = FindFileInSearchPaths( ss, aBaseName, &altsubdirs );
if( !fn )
fn = FindFileInSearchPaths( ss, aBaseName, &subdirs );
}
// Step 3 : if not found Try to find help file in help/en
if( !fn )
{
subdirs.RemoveAt( subdirs.GetCount() - 1 );
altsubdirs.RemoveAt( altsubdirs.GetCount() - 1 );
subdirs.Add( wxT( "en" ) );
altsubdirs.Add( wxT( "en" ) );
fn = FindFileInSearchPaths( ss, aBaseName, &altsubdirs );
if( !fn )
fn = FindFileInSearchPaths( ss, aBaseName, &subdirs );
}
return fn;
}
......@@ -34,6 +34,7 @@
*/
#include <typeinfo>
#include <macros.h>
#include <fctsys.h>
#include <wx/dynlib.h>
......@@ -182,10 +183,6 @@ static const wxString dso_full_path( const wxString& aAbsoluteArgv0 )
return fn.GetFullPath();
}
// Use of this is arbitrary, remember single_top only knows about a single DSO.
// Could have used one from the KIWAY also.
static wxDynamicLibrary dso;
// Only a single KIWAY is supported in this single_top top level component,
// which is dedicated to loading only a single DSO.
......@@ -230,6 +227,32 @@ struct APP_SINGLE_TOP : public wxApp
return wxApp::OnExit();
}
int OnRun() // overload wxApp virtual
{
try
{
return wxApp::OnRun();
}
catch( const std::exception& e )
{
wxLogError( wxT( "Unhandled exception class: %s what: %s" ),
GetChars( FROM_UTF8( typeid(e).name() )),
GetChars( FROM_UTF8( e.what() ) ) );;
}
catch( const IO_ERROR& ioe )
{
wxLogError( wxT( "Unhandled exception class: %s what: %s" ),
GetChars( FROM_UTF8( typeid( ioe ).name() ) ),
GetChars( ioe.errorText ) );
}
catch(...)
{
wxLogError( wxT( "Unhandled exception of unknown type" ) );
}
return -1;
}
/**
* Function MacOpenFile
* is specific to MacOSX (not used under Linux or Windows).
......@@ -261,6 +284,15 @@ IMPLEMENT_APP( APP_SINGLE_TOP );
static KIFACE_GETTER_FUNC* get_kiface_getter( const wxString& aDSOName )
{
#if defined(BUILD_KIWAY_DLL)
// Remember single_top only knows about a single DSO. Using an automatic
// with a defeated destructor, see Detach() below, so that the DSO program
// image stays in RAM until process termination, and specifically
// beyond the point in time at which static destructors are run. Otherwise
// a static wxDynamicLibrary's destructor might create an out of sequence
// problem. This was never detected, so it's only a preventative strategy.
wxDynamicLibrary dso;
void* addr = NULL;
if( !dso.Load( aDSOName, wxDL_VERBATIM | wxDL_NOW ) )
......@@ -275,6 +307,9 @@ static KIFACE_GETTER_FUNC* get_kiface_getter( const wxString& aDSOName )
// No further reporting required here.
}
// Tell dso's wxDynamicLibrary destructor not to Unload() the program image.
(void) dso.Detach();
return (KIFACE_GETTER_FUNC*) addr;
#else
......
......@@ -107,7 +107,7 @@ void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event )
{
fn.SetExt( fn.GetExt() + wxT( "." ) + FootprintAliasFileExtension );
}
tmp = search.FindValidPath( fn );
tmp = search.FindValidPath( fn.GetFullPath() );
if( !tmp )
{
......
......@@ -27,7 +27,7 @@
*/
#include <fctsys.h>
#include <pgm_base.h>
#include <kiface_i.h>
#include <fp_lib_table.h>
#include <id.h>
#include <common.h>
......@@ -42,29 +42,24 @@
#include <class_DisplayFootprintsFrame.h>
#define GROUP wxT("/cvpcb")
#define GROUPLIB wxT("/pcbnew/libraries")
#define GROUPEQU wxT("/cvpcb/libraries")
PARAM_CFG_ARRAY& CVPCB_MAINFRAME::GetProjectFileParameters()
{
if( !m_projectFileParams.empty() )
return m_projectFileParams;
m_projectFileParams.push_back( new PARAM_CFG_BASE( GROUPLIB, PARAM_COMMAND_ERASE ) );
m_projectFileParams.push_back( new PARAM_CFG_BASE( GROUP_PCB_LIBS, PARAM_COMMAND_ERASE ) );
m_projectFileParams.push_back( new PARAM_CFG_LIBNAME_LIST(
wxT( "LibName" ), &m_ModuleLibNames, GROUPLIB ) );
wxT( "LibName" ), &m_ModuleLibNames, GROUP_PCB_LIBS ) );
m_projectFileParams.push_back( new PARAM_CFG_LIBNAME_LIST(
wxT( "EquName" ), &m_AliasLibNames, GROUPEQU ) );
wxT( "EquName" ), &m_AliasLibNames, GROUP_CVP_EQU ) );
m_projectFileParams.push_back( new PARAM_CFG_WXSTRING(
wxT( "NetIExt" ), &m_NetlistFileExtension ) );
m_projectFileParams.push_back( new PARAM_CFG_FILENAME(
wxT( "LibDir" ), &m_UserLibraryPath, GROUPLIB ) );
wxT( "LibDir" ), &m_UserLibraryPath, GROUP_PCB_LIBS ) );
return m_projectFileParams;
}
......@@ -81,7 +76,7 @@ void CVPCB_MAINFRAME::LoadProjectFile( const wxString& aFileName )
fn.SetExt( ProjectFileExtension );
// was: Pgm().ReadProjectConfig( fn.GetFullPath(), GROUP, GetProjectFileParameters(), false );
prj.ConfigLoad( prj.PcbSearchS(), fn.GetFullPath(), GROUP, GetProjectFileParameters(), false );
prj.ConfigLoad( Kiface().KifaceSearch(), fn.GetFullPath(), GROUP_CVP, GetProjectFileParameters(), false );
if( m_NetlistFileExtension.IsEmpty() )
m_NetlistFileExtension = wxT( "net" );
......@@ -133,7 +128,7 @@ void CVPCB_MAINFRAME::SaveProjectFile( wxCommandEvent& aEvent )
// Pgm().WriteProjectConfig( fn.GetFullPath(), GROUP, GetProjectFileParameters() );
PROJECT& prj = Prj();
SEARCH_STACK& search = prj.SchSearchS();
prj.ConfigSave( search, fn.GetFullPath(), GROUP, GetProjectFileParameters() );
prj.ConfigSave( Kiface().KifaceSearch(), fn.GetFullPath(), GROUP_CVP, GetProjectFileParameters() );
}
......@@ -490,7 +490,7 @@ MODULE* DISPLAY_FOOTPRINTS_FRAME::Get_Module( const wxString& aFootprintName )
footprint = FootprintLibs()->FootprintLoad( FROM_UTF8( nickname.c_str() ), FROM_UTF8( fpname.c_str() ) );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
DisplayError( this, ioe.errorText );
return NULL;
......
......@@ -301,13 +301,6 @@ void CVPCB_MAINFRAME::OnCloseWindow( wxCloseEvent& Event )
}
}
// Close the help frame
if( Pgm().GetHtmlHelpController() )
{
if( Pgm().GetHtmlHelpController()->GetFrame() )// returns NULL if no help frame active
Pgm().GetHtmlHelpController()->GetFrame()->Close( true );
}
if( m_NetlistFileName.IsOk() )
{
UpdateFileHistory( m_NetlistFileName.GetFullPath() );
......@@ -846,7 +839,7 @@ int CVPCB_MAINFRAME::ReadSchematicNetlist()
else
wxMessageBox( _( "Unknown netlist format." ), wxEmptyString, wxOK | wxICON_ERROR );
}
catch( IO_ERROR& ioe )
catch( const IO_ERROR& ioe )
{
msg = wxString::Format( _( "Error loading netlist.\n%s" ), ioe.errorText.GetData() );
wxMessageBox( msg, _( "Netlist Load Error" ), wxOK | wxICON_ERROR );
......
......@@ -119,6 +119,20 @@ void CVPCB_MAINFRAME::SetNewPkg( const wxString& aFootprintName )
}
#if 0
/*
This code block was based on two major assumptions that are no longer true:
1) Footprint library basenames would remain the same.
(But no, basenames have been renamed in the github repo.)
2) *.mod files would still be around and merely reside in the FP_LIB_TABLE.
(But no, they have been converted to *.pretty.)
There is a newer replacement code block in the #else region.
*/
/**
* Function missingLegacyLibs
* tests the list of \a aLibNames by URI to determine if any of them are missing from
......@@ -138,23 +152,175 @@ void CVPCB_MAINFRAME::SetNewPkg( const wxString& aFootprintName )
static bool missingLegacyLibs( FP_LIB_TABLE* aTbl, SEARCH_STACK& aSStack,
const wxArrayString& aLibNames, wxString* aErrorMsg )
{
bool retv = false;
bool missing = false;
for( unsigned i = 0; i < aLibNames.GetCount(); i++ )
{
wxFileName fn( wxEmptyString, aLibNames[i], LegacyFootprintLibPathExtension );
wxString legacyLibPath = aSStack.FindValidPath( fn );
wxString legacyLibPath = aSStack.FindValidPath( fn.GetFullPath() );
/*
if( legacyLibPath.IsEmpty() )
continue;
*/
if( aTbl->FindRowByURI( legacyLibPath ) == 0 )
if( !aTbl->FindRowByURI( legacyLibPath ) )
{
retv = true;
missing = true;
if( aErrorMsg )
*aErrorMsg += wxT( "\"" ) + legacyLibPath + wxT( "\"\n" );
{
*aErrorMsg += wxChar( '"' );
if( !legacyLibPath )
*aErrorMsg += !legacyLibPath ? aLibNames[i] : legacyLibPath;
*aErrorMsg += wxT( "\"\n" );
}
}
}
return missing;
}
/**
* Function convertFromLegacy
* converts the footprint names in \a aNetList from the legacy format to the #FPID format.
*
* @param aNetList is the #NETLIST object to convert.
* @param aLibNames is the list of legacy footprint library names from the currently loaded
* project.
* @param aReporter is the #REPORTER object to dump messages into.
* @return true if all footprint names were successfully converted to a valid FPID.
*/
static bool convertFromLegacy( FP_LIB_TABLE* aTbl, SEARCH_STACK& aSStack, NETLIST& aNetList,
const wxArrayString& aLibNames, REPORTER* aReporter = NULL ) throw( IO_ERROR )
{
wxString msg;
FPID lastFPID;
COMPONENT* component;
MODULE* module = 0;
bool retv = true;
if( aNetList.IsEmpty() )
return true;
aNetList.SortByFPID();
wxString libPath;
PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::LEGACY ) );
for( unsigned ii = 0; ii < aNetList.GetCount(); ii++ )
{
component = aNetList.GetComponent( ii );
// The footprint hasn't been assigned yet so ignore it.
if( component->GetFPID().empty() )
continue;
if( component->GetFPID() != lastFPID )
{
module = NULL;
for( unsigned ii = 0; ii < aLibNames.GetCount(); ii++ )
{
wxFileName fn( wxEmptyString, aLibNames[ii], LegacyFootprintLibPathExtension );
libPath = aSStack.FindValidPath( fn.GetFullPath() );
if( !libPath )
{
if( aReporter )
{
msg.Printf( _( "Cannot find footprint library file '%s' in any of the "
"KiCad legacy library search paths.\n" ),
GetChars( fn.GetFullPath() ) );
aReporter->Report( msg );
}
retv = false;
continue;
}
module = pi->FootprintLoad( libPath, component->GetFPID().GetFootprintName() );
if( module )
{
lastFPID = component->GetFPID();
break;
}
}
}
if( !module )
{
if( aReporter )
{
msg.Printf( _( "Component '%s' footprint '%s' was not found in any legacy "
"library.\n" ),
GetChars( component->GetReference() ),
GetChars( component->GetFPID().Format() ) );
aReporter->Report( msg );
}
// Clear the footprint assignment since the old library lookup method is no
// longer valid.
FPID emptyFPID;
component->SetFPID( emptyFPID );
retv = false;
continue;
}
else
{
wxString libNickname;
const FP_LIB_TABLE::ROW* row;
if( ( row = aTbl->FindRowByURI( libPath ) ) != NULL )
libNickname = row->GetNickName();
if( libNickname.IsEmpty() )
{
if( aReporter )
{
msg.Printf( _( "Component '%s' with footprint '%s' and legacy library path '%s' "
"was not found in the footprint library table.\n" ),
GetChars( component->GetReference() ),
GetChars( component->GetFPID().Format() ),
GetChars( libPath )
);
aReporter->Report( msg );
}
retv = false;
}
else
{
FPID newFPID = lastFPID;
newFPID.SetLibNickname( libNickname );
if( !newFPID.IsValid() )
{
if( aReporter )
{
msg.Printf( _( "Component '%s' FPID '%s' is not valid.\n" ),
GetChars( component->GetReference() ),
GetChars( newFPID.Format() ) );
aReporter->Report( msg );
}
retv = false;
}
else
{
// The footprint name should already be set.
component->SetFPID( newFPID );
}
}
}
}
......@@ -210,7 +376,7 @@ bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles()
if( missingLegacyLibs( FootprintLibs(), Prj().PcbSearchS(), m_ModuleLibNames, &missingLibs ) )
{
msg = wxT( "The following legacy libraries are defined in the project file "
"were not found in the footprint library table:\n\n" ) + missingLibs;
"but were not found in the footprint library table:\n\n" ) + missingLibs;
msg += wxT( "\nDo you want to update the footprint library table before "
"attempting to update the assigned footprints?" );
......@@ -233,11 +399,11 @@ bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles()
SEARCH_STACK& search = Prj().SchSearchS();
if( !FootprintLibs()->ConvertFromLegacy( search, m_netlist, m_ModuleLibNames, &reporter ) )
if( !convertFromLegacy( FootprintLibs(), search, m_netlist, m_ModuleLibNames, &reporter ) )
{
HTML_MESSAGE_BOX dlg( this, wxEmptyString );
dlg.MessageSet( wxT( "The following errors occurred attempt to convert the "
dlg.MessageSet( wxT( "The following errors occurred attempting to convert the "
"footprint assignments:\n\n" ) );
dlg.ListSet( msg );
dlg.MessageSet( wxT( "\nYou will need to reassign them manually if you want them "
......@@ -291,6 +457,210 @@ bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles()
return true;
}
#else // new strategy
/// Return true if the resultant FPID has a certain nickname. The guess
/// is only made if this footprint resides in only one library.
/// @return int - 0 on success, 1 on not found, 2 on ambiguous i.e. multiple matches
static int guessNickname( FP_LIB_TABLE* aTbl, FPID* aFootprintId )
{
if( aFootprintId->GetLibNickname().size() )
return 0;
wxString nick;
wxString fpname = aFootprintId->GetFootprintName();
std::vector<wxString> nicks = aTbl->GetLogicalLibs();
// Search each library going through libraries alphabetically.
for( unsigned libNdx = 0; libNdx<nicks.size(); ++libNdx )
{
wxArrayString fpnames = aTbl->FootprintEnumerate( nicks[libNdx] );
for( unsigned nameNdx = 0; nameNdx<fpnames.size(); ++nameNdx )
{
if( fpname == fpnames[nameNdx] )
{
if( !nick )
nick = nicks[libNdx];
else
return 2; // duplicate, the guess would not be certain
}
}
}
if( nick.size() )
{
aFootprintId->SetLibNickname( nick );
return 0;
}
return 1;
}
bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles()
{
wxString msg;
bool hasMissingNicks = false;
FP_LIB_TABLE* tbl = FootprintLibs();
ReadSchematicNetlist();
if( m_ListCmp == NULL )
return false;
LoadProjectFile( m_NetlistFileName.GetFullPath() );
LoadFootprintFiles();
BuildFOOTPRINTS_LISTBOX();
BuildLIBRARY_LISTBOX();
m_ListCmp->Clear();
m_undefinedComponentCnt = 0;
if( m_netlist.AnyFootprintsLinked() )
{
for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
{
COMPONENT* component = m_netlist.GetComponent( i );
if( component->GetFPID().empty() )
continue;
if( component->GetFPID().IsLegacy() )
hasMissingNicks = true;
}
}
// Check if footprint links were generated before the footprint library table was implemented.
if( hasMissingNicks )
{
msg = wxT(
"Some of the assigned footprints are legacy entries (are missing lib nicknames). "
"Would you like CvPcb to attempt to convert them to the new required FPID format? "
"(If you answer no, then these assignments will be cleared out and you will "
"have to re-assign these footprints yourself.)"
);
if( IsOK( this, msg ) )
{
msg.Clear();
try
{
for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
{
COMPONENT* component = m_netlist.GetComponent( i );
if( component->GetFPID().IsLegacy() )
{
int guess = guessNickname( tbl, (FPID*) &component->GetFPID() );
switch( guess )
{
case 0:
DBG(printf("%s: guessed OK ref:%s fpid:%s\n", __func__,
TO_UTF8( component->GetReference() ), component->GetFPID().Format().c_str() );)
m_modified = true;
break;
case 1:
msg += wxString::Format( _(
"Component '%s' footprint '%s' was <b>not found</b> in any library.\n" ),
GetChars( component->GetReference() ),
GetChars( component->GetFPID().GetFootprintName() )
);
break;
case 2:
msg += wxString::Format( _(
"Component '%s' footprint '%s' was found in <b>multiple</b> libraries.\n" ),
GetChars( component->GetReference() ),
GetChars( component->GetFPID().GetFootprintName() )
);
break;
}
}
}
}
catch( const IO_ERROR& ioe )
{
wxString msg = ioe.errorText;
msg += wxT( "\n\n" );
msg += _( "First check your fp-lib-table entries." );
wxMessageBox( msg, wxT( "Problematic fp-lib-tables" ) );
return false;
}
if( msg.size() )
{
HTML_MESSAGE_BOX dlg( this, wxEmptyString );
dlg.MessageSet( wxT( "The following errors occurred attempting to convert the "
"footprint assignments:\n\n" ) );
dlg.ListSet( msg );
dlg.MessageSet( wxT( "\nYou will need to reassign them manually if you want them "
"to be updated correctly the next time you import the "
"netlist in Pcbnew." ) );
#if 1
dlg.ShowModal();
#else
dlg.Fit();
dlg.Show( true ); // modeless lets user watch while fixing the problems, but its not working.
#endif
}
}
else
{
// Clear the legacy footprint assignments.
for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
{
COMPONENT* component = m_netlist.GetComponent( i );
if( component->GetFPID().IsLegacy() )
{
component->SetFPID( FPID() /* empty */ );
m_modified = true;
}
}
}
}
for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
{
COMPONENT* component = m_netlist.GetComponent( i );
msg.Printf( CMP_FORMAT, m_ListCmp->GetCount() + 1,
GetChars( component->GetReference() ),
GetChars( component->GetValue() ),
GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
m_ListCmp->AppendLine( msg );
if( component->GetFPID().empty() )
{
m_undefinedComponentCnt += 1;
continue;
}
}
if( !m_netlist.IsEmpty() )
m_ListCmp->SetSelection( 0, true );
DisplayStatus();
UpdateTitle();
UpdateFileHistory( m_NetlistFileName.GetFullPath() );
return true;
}
#endif
int CVPCB_MAINFRAME::SaveCmpLinkFile( const wxString& aFullFileName )
{
......
......@@ -136,7 +136,7 @@ bool LIB_ALIAS::SaveDoc( OUTPUTFORMATTER& aFormatter )
aFormatter.Print( 0, "$ENDCMP\n" );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
return false;
}
......
......@@ -731,7 +731,7 @@ bool CMP_LIBRARY::Save( OUTPUTFORMATTER& aFormatter )
aFormatter.Print( 0, "#\n#End Library\n" );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
success = false;
}
......@@ -756,7 +756,7 @@ bool CMP_LIBRARY::SaveDocs( OUTPUTFORMATTER& aFormatter )
aFormatter.Print( 0, "#\n#End Doc Library\n" );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
success = false;
}
......
......@@ -249,7 +249,7 @@ void DIALOG_BOM::installPluginsList()
{
cfg_parser.Parse();
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
// wxLogMessage( ioe.errorText );
}
......
......@@ -62,7 +62,7 @@ void SCH_EDIT_FRAME::LoadLibraries()
if( !fn.FileExists() )
{
tmp = lib_search.FindValidPath( fn );
tmp = lib_search.FindValidPath( fn.GetFullPath() );
if( !tmp )
{
......
......@@ -368,7 +368,7 @@ PARAM_CFG_ARRAY& SCH_EDIT_FRAME::GetProjectFileParametersList()
&m_userLibraryPath ) );
m_projectFileParams.push_back( new PARAM_CFG_LIBNAME_LIST( wxT( "LibName" ),
&m_componentLibFiles,
GROUPLIB ) );
GROUP_SCH_LIBS ) );
m_projectFileParams.push_back( new PARAM_CFG_WXSTRING( wxT( "NetFmtName" ),
&m_netListFormat) );
......@@ -408,7 +408,7 @@ bool SCH_EDIT_FRAME::LoadProjectFile( const wxString& aFileName, bool aForceRere
// extension (.pro).
fn.SetExt( ProjectFileExtension );
if( !prj.ConfigLoad( Kiface().KifaceSearch(), fn.GetFullPath(), GROUP,
if( !prj.ConfigLoad( Kiface().KifaceSearch(), fn.GetFullPath(), GROUP_SCH,
GetProjectFileParametersList(), !aForceReread ) )
{
m_componentLibFiles = liblist_tmp;
......@@ -427,7 +427,7 @@ bool SCH_EDIT_FRAME::LoadProjectFile( const wxString& aFileName, bool aForceRere
pglayout.SetPageLayout(BASE_SCREEN::m_PageLayoutDescrFileName);
// libraries in the *.pro file take precedence over standard library search paths,
// but not over the director of the project, which is at index 0.
// but not over the directory of the project, which is at index 0.
prj.SchSearchS().AddPaths( m_userLibraryPath, 1 );
// If the list is empty, force loading the standard power symbol library.
......@@ -464,7 +464,7 @@ void SCH_EDIT_FRAME::SaveProjectSettings( bool aAskForSave )
}
prj.ConfigSave( Kiface().KifaceSearch(),
fn.GetFullPath(), GROUP, GetProjectFileParametersList() );
fn.GetFullPath(), GROUP_SCH, GetProjectFileParametersList() );
}
......@@ -666,7 +666,7 @@ void SCH_EDIT_FRAME::LoadSettings( wxConfigBase* aCfg )
{
m_TemplateFieldNames.Parse( &lexer );
}
catch( IO_ERROR& e )
catch( const IO_ERROR& e )
{
// @todo show error msg
DBG( printf( "templatefieldnames parsing error: '%s'\n",
......
......@@ -4,9 +4,6 @@
#include <config_params.h>
#define GROUP wxT( "/eeschema" )
#define GROUPCOMMON wxT( "/common" )
#define GROUPLIB wxT( "libraries" )
/* saving parameters option : */
#define INSETUP true /* used when the parameter is saved in general config
......
......@@ -1049,7 +1049,7 @@ bool NETLIST_EXPORT_TOOL::WriteKiCadNetList( const wxString& aOutFileName )
xroot->Format( &formatter, 0 );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
DisplayError( NULL, ioe.errorText );
return false;
......
......@@ -868,7 +868,7 @@ void SCH_EDIT_FRAME::OnPrint( wxCommandEvent& event )
// was: wxGetApp().WriteProjectConfig( fn.GetFullPath(), GROUP, GetProjectFileParametersList() );
Prj().ConfigSave( Kiface().KifaceSearch(),
fn.GetFullPath(), GROUP, GetProjectFileParametersList() );
fn.GetFullPath(), GROUP_SCH, GetProjectFileParametersList() );
}
}
......
......@@ -225,14 +225,14 @@ void LIB_EDIT_FRAME::SaveOneSymbol()
formatter.Print( 0, "ENDDRAW\n" );
formatter.Print( 0, "ENDDEF\n" );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
msg.Printf( _( "An error occurred attempting to save symbol file '%s'" ),
GetChars( fn.GetFullPath() ) );
DisplayError( this, msg );
}
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
DisplayError( this, ioe.errorText );
return;
......
......@@ -59,6 +59,8 @@ struct BIN_MOD
wxString m_help_file;
SEARCH_STACK m_search;
};
#endif // BIN_MOD_H_
......@@ -589,4 +589,25 @@ wxString FormatDateLong( const wxDateTime &aDate );
*/
void SystemDirsAppend( SEARCH_STACK* aSearchStack );
/**
* Function SearchHelpFileFullPath
* returns the help file's full path.
* <p>
* Return the KiCad help file with path.
* If the help file for the current locale is not found, an attempt to find
* the English version of the help file is made.
* Help file is searched in directories in this order:
* help/\<canonical name\> like help/en_GB
* help/\<short name\> like help/en
* help/en
* </p>
* @param aSearchStack contains some possible base dirs that may be above the
* the one actually holding @a aBaseName. These are starting points for nested searches.
* @param aBaseName is the name of the help file to search for.
* @return wxEmptyString is returned if aBaseName is not found, else the full path & filename.
*/
wxString SearchHelpFileFullPath( const SEARCH_STACK& aSearchStack, const wxString& aBaseName );
#endif // INCLUDE__COMMON_H_
......@@ -37,6 +37,17 @@
#include <limits>
#define GROUP_PCB wxT( "/pcbnew" )
#define GROUP_SCH wxT( "/eeschema" )
#define GROUP_PCB_LIBS wxT( "/pcbnew/libraries" )
#define GROUP_SCH_LIBS wxT( "/eeschema/libraries" )
#define GROUP_COMMON wxT( "/common" )
#define GROUP_CVP wxT("/cvpcb")
//#define GROUP_CVP_LIBS wxT("/pcbnew/libraries")
#define GROUP_CVP_EQU wxT("/cvpcb/libraries")
#define CONFIG_VERSION 1
#define FORCE_LOCAL_CONFIG true
......
......@@ -38,6 +38,7 @@ class wxFileName;
class OUTPUTFORMATTER;
class MODULE;
class FP_LIB_TABLE_LEXER;
class FPID;
class NETLIST;
class REPORTER;
class SEARCH_STACK;
......@@ -455,6 +456,21 @@ public:
//-----</PLUGIN API SUBSET, REBASED ON aNickname>---------------------------
/**
* Function FootprintLoadWithOptionalNickname
* loads a footprint having @a aFootprintId with possibly an empty nickname.
*
* @param aFootprintId the [nickname] & fooprint name of the footprint to load.
*
* @return MODULE* - if found caller owns it, else NULL if not found.
*
* @throw IO_ERROR if the library cannot be found or read. No exception
* is thrown in the case where aFootprintName cannot be found.
* @throw PARSE_ERROR if @a aFootprintId is not parsed OK.
*/
MODULE* FootprintLoadWithOptionalNickname( const FPID& aFootprintId )
throw( IO_ERROR, PARSE_ERROR );
/**
* Function GetDescription
* returns the library desicription from @a aNickname, or an empty string
......@@ -499,19 +515,6 @@ public:
*/
bool IsEmpty( bool aIncludeFallback = true );
/**
* Function ConvertFromLegacy
* converts the footprint names in \a aNetList from the legacy format to the #FPID format.
*
* @param aNetList is the #NETLIST object to convert.
* @param aLibNames is the list of legacy footprint library names from the currently loaded
* project.
* @param aReporter is the #REPORTER object to dump messages into.
* @return true if all footprint names were successfully converted to a valid FPID.
*/
bool ConvertFromLegacy( SEARCH_STACK& aSStack, NETLIST& aNetList,
const wxArrayString& aLibNames, REPORTER* aReporter = NULL ) throw( IO_ERROR );
/**
* Function ExpandSubstitutions
* replaces any environment variable references with their values and is
......
......@@ -153,7 +153,6 @@ public:
*/
bool IsValid() const { return !nickname.empty() && !footprint.empty(); }
/**
* Function IsLegacy
* @return true if the #FPID only has the #footprint name defined.
......
......@@ -89,28 +89,6 @@ int ExecuteFile( wxWindow* frame, const wxString& ExecFile,
*/
void AddDelimiterString( wxString& string );
/**
* Function FindKicadHelpPath
* finds the absolute path for KiCad "help" (or "help/&ltlanguage&gt")
* Find path kicad/doc/help/xx/ or kicad/doc/help/:
* from BinDir
* else from environment variable KICAD
* else from one of s_HelpPathList
* typically c:/kicad/doc/help or /usr/share/kicad/help
* or /usr/local/share/kicad/help
* (must have kicad in path name)
*
* xx = iso639-1 language id (2 letters (generic) or 4 letters):
* fr = french (or fr_FR)
* en = English (or en_GB or en_US ...)
* de = deutch
* es = spanish
* pt = portuguese (or pt_BR ...)
*
* default = en (if not found = fr)
*/
wxString FindKicadHelpPath();
/**
* Function KicadDatasPath
* returns the data path common to KiCad.
......
......@@ -100,33 +100,17 @@ public:
wxConfigBase* KifaceSettings() const { return m_bm.m_config; }
const wxString& GetHelpFileName() const { return m_bm.m_help_file; }
void SetHelpFileName( const wxString& aFileName ) { m_bm.m_help_file = aFileName; }
/**
* Function GetHelpFile
* gets the help file path.
* <p>
* Return the KiCad help file with path. The base paths defined in
* m_searchPaths are tested for a valid file. The path returned can
* be relative depending on the paths added to m_searchPaths. See the
* documentation for wxPathList for more information. If the help file
* for the current locale is not found, an attempt to find the English
* version of the help file is made.
* wxEmptyString is returned if help file not found.
* Help file is searched in directories in this order:
* help/\<canonical name\> like help/en_GB
* help/\<short name\> like help/en
* help/en
* </p>
* Function GetHelpFileName
* returns just the basename portion of the current help file.
*/
wxString GetHelpFile();
const wxString& GetHelpFileName() const { return m_bm.m_help_file; }
wxFileHistory& GetFileHistory() { return m_bm.m_history; }
wxFileHistory& GetFileHistory() { return m_bm.m_history; }
/// Only for DSO specific 'non-library' files.
/// (The library search path is in the PROJECT class.)
SEARCH_STACK& KifaceSearch() { return m_bm.m_search; }
SEARCH_STACK& KifaceSearch() { return m_bm.m_search; }
private:
KIWAY::FACE_T m_id;
......
......@@ -86,9 +86,7 @@ public:
//----<Cross Module API>-----------------------------------------------------
VTBL_ENTRY wxHtmlHelpController* GetHtmlHelpController() { return m_html_ctrl; }
VTBL_ENTRY void SetHtmlHelpController( wxHtmlHelpController* aController );
VTBL_ENTRY wxHtmlHelpController* HtmlHelpController();
VTBL_ENTRY wxConfigBase* CommonSettings() const { return m_common_settings; }
......@@ -161,12 +159,6 @@ public:
VTBL_ENTRY void SetLanguagePath();
/**
* Function InitOnLineHelp
* initializes KiCad's online help.
*/
VTBL_ENTRY void InitOnLineHelp();
/**
* Function ReadPdfBrowserInfos
* reads the PDF browser choice from the common configuration.
......@@ -217,6 +209,8 @@ protected:
*/
bool initPgm();
void initHtmlHelpController();
/**
* Function loadCommonSettings
* loads the program (process) settings subset which are stored in .kicad_common
......
......@@ -131,15 +131,6 @@ public:
/// Accessor for Eeschema search stack.
VTBL_ENTRY SEARCH_STACK& SchSearchS() { return m_sch_search; }
/**
* Function PcbSearchS
* returns the obsolete footprint library search stack.
* Projects created before the FP_LIB_TABLE support will have footprint
* search paths in the *.pro files. Projects created after the FP_LIB_TABLE
* support will not. This stack is used for conversion from old to new only.
*/
VTBL_ENTRY SEARCH_STACK& PcbSearchS() { return m_pcb_search; }
VTBL_ENTRY wxString GetModuleLibraryNickname() { return m_module_library_nickname; }
VTBL_ENTRY void SetModuleLibraryNickname( const wxString& aNickName ) { m_module_library_nickname = aNickName; }
......
......@@ -78,7 +78,7 @@ typedef const PTREE CPTREE;
* PTREE doc;
* Scan( &doc, &lexer );
* }
* catch( IO_ERROR ioe )
* catch( const IO_ERROR& ioe )
* {
* fprintf( stderr, "%s\n", TO_UTF8( ioe.errorText ) );
* }
......
......@@ -39,21 +39,6 @@ public:
return wxPathList::FindValidPath( aFileName );
}
/**
* Function FindValidPath
* KiCad saves user defined library files that are not in the standard
* library search path list with the full file path. Calling the library
* search path list with a user library file will fail. This helper method
* solves that problem.
* @param fileName
* @return a wxEmptyString if library file is not found.
*/
wxString FindValidPath( const wxFileName& aFileName ) const
{
// call wxPathList::FindValidPath( const wxString& );
return wxPathList::FindValidPath( aFileName.GetFullPath() );
}
/**
* Function AddPaths
* insert or append path(s)
......@@ -72,15 +57,6 @@ public:
* ";" on windows, or ":" | ";" on unix.
*/
void RemovePaths( const wxString& aPaths );
/**
* Function FindFileInSearchPaths
* looks in "this" for \a aFilename, but first modifies every search
* path by appending a list of path fragments from aSubdirs. That modification
* is not rentative.
*/
wxString FindFileInSearchPaths( const wxString& aFilename,
const wxArrayString* aSubdirs = NULL );
};
......
......@@ -186,6 +186,15 @@ protected:
*/
virtual wxConfigBase* config();
/**
* Function sys_search
* returns a SEARCH_STACK pertaining to entire program, and is overloaded in
* KICAD_MANAGER_FRAME
*/
virtual const SEARCH_STACK& sys_search();
virtual wxString help_name();
public:
EDA_BASE_FRAME( wxWindow* aParent, ID_DRAWFRAME_TYPE aFrameType,
const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize,
......
......@@ -123,6 +123,11 @@ class KICAD_MANAGER_FRAME : public EDA_BASE_FRAME
protected:
wxConfigBase* config(); // override EDA_BASE_FRAME virtual
const SEARCH_STACK& sys_search(); // override EDA_BASE_FRAME virtual
wxString help_name(); // override EDA_BASE_FRAME virtual
public:
TREE_PROJECT_FRAME* m_LeftWin;
LAUNCHER_PANEL* m_Launcher;
......
......@@ -123,6 +123,18 @@ wxConfigBase* KICAD_MANAGER_FRAME::config()
}
const SEARCH_STACK& KICAD_MANAGER_FRAME::sys_search()
{
return Pgm().SysSearch();
}
wxString KICAD_MANAGER_FRAME::help_name()
{
return Pgm().GetHelpFileName();
}
void KICAD_MANAGER_FRAME::PrintMsg( const wxString& aText )
{
m_MessagesBox->AppendText( aText );
......@@ -157,15 +169,6 @@ void KICAD_MANAGER_FRAME::OnCloseWindow( wxCloseEvent& Event )
Event.SetCanVeto( true );
// Close the help frame
if( Pgm().GetHtmlHelpController() )
{
if( Pgm().GetHtmlHelpController()->GetFrame() ) // returns NULL if no help frame active
Pgm().GetHtmlHelpController()->GetFrame()->Close( true );
Pgm().SetHtmlHelpController( NULL );
}
m_LeftWin->Show( false );
Destroy();
......
......@@ -58,6 +58,8 @@ public:
SEARCH_STACK& SysSearch() { return m_bm.m_search; }
wxString GetHelpFileName() { return m_bm.m_help_file; }
protected:
// The PGM_* classes can have difficulties at termination if they
......
......@@ -94,10 +94,10 @@ static const wxChar* s_allowedExtensionsToList[] =
*/
/* File extension definitions. */
const wxString TextFileExtension( wxT( "txt" ) );
const wxChar TextFileExtension[] = wxT( "txt" );
/* File wildcard definitions. */
const wxString TextFileWildcard( wxT( "Text files (*.txt)|*.txt" ) );
const wxChar TextFileWildcard[] = wxT( "Text files (*.txt)|*.txt" );
/**
......@@ -177,7 +177,6 @@ void TREE_PROJECT_FRAME::RemoveFilter( const wxString& filter )
}
/**
* Called by the popup menu in the tree frame
* Creates a new subdirectory inside the current kicad project directory
......
......@@ -716,7 +716,7 @@ void DIR_LIB_SOURCE::Test( int argc, char** argv )
printf( "std::exception\n" );
}
catch( IO_ERROR& ioe )
catch( const IO_ERROR& ioe )
{
printf( "exception: %s\n", (const char*) ioe.errorText.ToUTF8() ) );
}
......
......@@ -118,7 +118,7 @@ int main( int argc, char** argv )
printf( "%*s^\n", ioe.byteIndex>=1 ? ioe.byteIndex-1 : 0, "" );
}
catch( IO_ERROR& ioe )
catch( const IO_ERROR& ioe )
{
printf( "%s\n", (const char*) ioe.errorText.ToUTF8() );
}
......
......@@ -98,7 +98,7 @@ public:
m_fileout = new FILE_OUTPUTFORMATTER( aFilename );
m_out = m_fileout;
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
wxMessageBox( ioe.errorText, _("Error writing page layout descr file" ) );
}
......@@ -125,7 +125,7 @@ public:
m_writer = new STRING_FORMATTER();
m_out = m_writer;
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
wxMessageBox( ioe.errorText, _("Error writing page layout descr file" ) );
}
......
......@@ -66,13 +66,16 @@ bool PCB_CALCULATOR_FRAME::ReadDataFile()
{
datafile_parser.Parse( datafile );
}
catch( IO_ERROR& ioe )
catch( const IO_ERROR& ioe )
{
delete datafile;
ioe.errorText += '\n';
ioe.errorText += _("Data file error.");
wxMessageBox( ioe.errorText );
wxString msg = ioe.errorText;
msg += wxChar('\n');
msg += _("Data file error.");
wxMessageBox( msg );
return false;
}
......@@ -99,7 +102,7 @@ bool PCB_CALCULATOR_FRAME::WriteDataFile()
while( nestlevel-- )
formatter.Print( nestlevel, ")\n" );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
return false;
}
......
......@@ -346,13 +346,10 @@ if( KICAD_SCRIPTING )
COMMAND ${SWIG_EXECUTABLE} ${SWIG_OPTS} -o ${CMAKE_CURRENT_BINARY_DIR}/pcbnew_wrap.cxx scripting/pcbnew.i
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripting/build_tools/fix_swig_imports.py ${CMAKE_CURRENT_BINARY_DIR}/pcbnew.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
)
endif()
###
# _pcbnew DLL/DSO file creation
###
if( BUILD_GITHUB_PLUGIN )
set( GITHUB_PLUGIN_LIBRARIES github_plugin )
......@@ -401,9 +398,14 @@ if( KICAD_SCRIPTING_MODULES )
if( MAKE_LINK_MAPS )
set_target_properties( _pcbnew PROPERTIES
LINK_FLAGS "${TO_LINKER},-cref ${TO_LINKER},-Map=pcbnew.so.map" )
LINK_FLAGS "${TO_LINKER},-cref ${TO_LINKER},-Map=pcbnew.so.map"
)
endif()
if( ${OPENMP_FOUND} )
set_property( TARGET _pcbnew APPEND_STRING
PROPERTY LINK_FLAGS " ${OpenMP_CXX_FLAGS}" )
endif()
endif()
......@@ -422,14 +424,13 @@ if( DOXYGEN_FOUND )
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS Doxyfile_xml
COMMENT "building doxygen docs into directory doxygen-python/html"
)
)
# create .i files from XML doxygen parsing, docstrings.i will include all of them
add_custom_target( xml-to-docstrings
COMMAND ${CMAKE_COMMAND} -E remove_directory docstrings
COMMAND ${CMAKE_COMMAND} -E make_directory docstrings
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripting/build_tools/extract_docstrings.py pcbnew.py doxygen-xml/xml docstrings
COMMAND ${CMAKE_COMMAND} -E remove pcbnew.py # force removal so it will be recreated later with the new docstrings
COMMENT "building docstring files"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
......@@ -445,16 +446,14 @@ if( DOXYGEN_FOUND )
DEPENDS Doxyfile_python
DEPENDS xml-to-docstrings
DEPENDS pcbnew.py
COMMENT "building doxygen docs into directory doxygen-python/html"
)
)
endif()
else()
message( STATUS "WARNING: Doxygen not found - doxygen-docs (Source Docs) target not created" )
endif()
if( MINGW )
# PCBNEW_RESOURCES variable is set by the macro.
mingw_resource_compiler( pcbnew )
......@@ -485,9 +484,8 @@ add_custom_command(
from ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_freeroute_exchange_help.html"
)
set_source_files_properties( dialogs/dialog_freeroute_exchange.cpp
PROPERTIES
OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_freeroute_exchange_help_html.h
set_source_files_properties( dialogs/dialog_freeroute_exchange.cpp PROPERTIES
OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_freeroute_exchange_help_html.h
)
......@@ -511,14 +509,14 @@ endif()
if( USE_KIWAY_DLLS )
#if( false )
# a very small program launcher for pcbnew_kiface
add_executable( pcbnew WIN32 MACOSX_BUNDLE
../common/single_top.cpp
../common/pgm_base.cpp
${PCBNEW_RESOURCES}
)
set_source_files_properties( ../common/single_top.cpp PROPERTIES
set_source_files_properties( ../common/single_top.cpp pcbnew.cpp PROPERTIES
COMPILE_DEFINITIONS "TOP_FRAME=PCB_FRAME_TYPE;PGM_DATA_FILE_EXT=\"kicad_pcb\";BUILD_KIWAY_DLL"
)
target_link_libraries( pcbnew
......@@ -539,9 +537,7 @@ if( USE_KIWAY_DLLS )
${PCBNEW_SRCS}
${PCBNEW_COMMON_SRCS}
${PCBNEW_SCRIPTING_SRCS}
# ${PCBNEW_RESOURCES}
)
set_target_properties( pcbnew_kiface PROPERTIES
# Decorate OUTPUT_NAME with PREFIX and SUFFIX, creating something like
# _pcbnew.so, _pcbnew.dll, or _pcbnew.kiface
......@@ -552,7 +548,7 @@ if( USE_KIWAY_DLLS )
if( ${OPENMP_FOUND} )
set_target_properties( pcbnew_kiface PROPERTIES
COMPILE_FLAGS ${OpenMP_CXX_FLAGS}
)
)
endif()
target_link_libraries( pcbnew_kiface
......@@ -583,7 +579,11 @@ if( USE_KIWAY_DLLS )
)
if( MAKE_LINK_MAPS )
set_target_properties( pcbnew_kiface PROPERTIES
LINK_FLAGS "${TO_LINKER},-cref ${TO_LINKER},-Map=_pcbnew.kiface.map" )
LINK_FLAGS "${TO_LINKER},-cref ${TO_LINKER},-Map=_pcbnew.kiface.map"
)
set_target_properties( pcbnew PROPERTIES
LINK_FLAGS "${TO_LINKER},-cref ${TO_LINKER},-Map=pcbnew.map"
)
endif()
# if building pcbnew, then also build pcbnew_kiface if out of date.
......@@ -605,18 +605,22 @@ if( USE_KIWAY_DLLS )
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/pcbnew/_pcbnew.kiface "${CMAKE_BINARY_DIR}/pcbnew/pcbnew.app/Contents/MacOS/"
DEPENDS pcbnew_kiface
COMMENT "Copying kiface into pcbnew"
)
)
endif()
else() # milestone A) kills this off:
add_executable( pcbnew WIN32 MACOSX_BUNDLE
../common/single_top.cpp
pcbnew.cpp
${PCBNEW_SRCS}
${PCBNEW_COMMON_SRCS}
${PCBNEW_SCRIPTING_SRCS}
${PCBNEW_RESOURCES}
)
set_source_files_properties( ../common/single_top.cpp PROPERTIES
COMPILE_DEFINITIONS "TOP_FRAME=PCB_FRAME_TYPE;PGM_DATA_FILE_EXT=\"kicad_pcb\""
)
target_link_libraries( pcbnew
3d-viewer
pcbcommon
......@@ -651,28 +655,25 @@ else() # milestone A) kills this off:
)
endif()
if( MAKE_LINK_MAPS )
# generate a link map with cross reference
set_target_properties( pcbnew PROPERTIES
LINK_FLAGS "${TO_LINKER},-cref ${TO_LINKER},-Map=pcbnew.map"
)
endif()
install( TARGETS pcbnew
DESTINATION ${KICAD_BIN}
COMPONENT binary
)
endif()
add_dependencies( pcbnew lib-dependencies )
###
# Set properties for APPLE on pcbnew target
###
if( APPLE )
set_target_properties( pcbnew PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist )
endif()
if( MAKE_LINK_MAPS )
# generate a link map with cross reference
set_target_properties( pcbnew PROPERTIES
LINK_FLAGS "${TO_LINKER},-cref ${TO_LINKER},-Map=pcbnew.map" )
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist
)
endif()
......@@ -691,19 +692,19 @@ if( KICAD_SCRIPTING )
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/pcbnew/pcbnew.py "${PYTHON_DEST}/wx-3.0-osx_cocoa/"
DEPENDS FixSwigImportsScripting
COMMENT "Copying pcbnew.py into PYTHON_DEST/wx-3.0-osx_cocoa/"
)
)
add_custom_target( pcbnew_copy_wxpython_scripting ALL
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBWXPYTHON_ROOT}/wxPython/ ${CMAKE_SOURCE_DIR}/pcbnew/pcbnew.app/Contents/Frameworks/wxPython/
DEPENDS FixSwigImportsScripting _pcbnew_py_copy
COMMENT "Copying wxPython into pcbnew.app Framework"
)
)
add_custom_target( pcbnew_copy_plugins ALL
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/pcbnew/scripting/plugins ${PROJECT_SOURCE_DIR}/pcbnew/pcbnew.app/Contents/PlugIns/scripting/plugins
DEPENDS pcbnew_copy_wxpython_scripting
COMMENT "Copying plugins into bundle"
)
)
# fix bundle after copying wxpython, fixing and copying
add_dependencies( osx_fix_bundles pcbnew_copy_wxpython_scripting )
......@@ -738,13 +739,13 @@ if( KICAD_SCRIPTING_MODULES )
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/pcbnew/_pcbnew.so "${PYTHON_DEST}"
DEPENDS _pcbnew FixSwigImportsModuleScripting
COMMENT "Copying _pcbnew.so into PYTHON_DEST"
)
)
add_custom_target( pcbnew_copy_wxpython_module ALL
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBWXPYTHON_ROOT}/wxPython/ ${PROJECT_SOURCE_DIR}/pcbnew/pcbnew.app/Contents/Frameworks/wxPython/
DEPENDS FixSwigImportsModuleScripting _pcbnew_so_copy
COMMENT "Copying wxPython into pcbnew.app Frameworks"
)
)
if( KICAD_BUILD_DYNAMIC )
# Tell that we have to run osx_fix_bundles fix after building _pcbnew and migrating wxPython
......@@ -755,14 +756,15 @@ if( KICAD_SCRIPTING_MODULES )
endif()
# This one gets made only when testing.
add_executable( specctra_test EXCLUDE_FROM_ALL specctra_test.cpp specctra.cpp )
target_link_libraries( specctra_test common ${wxWidgets_LIBRARIES} )
if( false ) # haven't been used in years.
# This one gets made only when testing.
add_executable( specctra_test EXCLUDE_FROM_ALL specctra_test.cpp specctra.cpp )
target_link_libraries( specctra_test common ${wxWidgets_LIBRARIES} )
# This one gets made only when testing.
add_executable( layer_widget_test WIN32 EXCLUDE_FROM_ALL
layer_widget.cpp
)
target_link_libraries( layer_widget_test common ${wxWidgets_LIBRARIES} )
# This one gets made only when testing.
add_executable( layer_widget_test WIN32 EXCLUDE_FROM_ALL
layer_widget.cpp
)
target_link_libraries( layer_widget_test common ${wxWidgets_LIBRARIES} )
endif()
......@@ -36,7 +36,7 @@
// This will get mapped to "kicad_default" in the specctra_export.
const wxString NETCLASS::Default = wxT("Default");
const wxChar NETCLASS::Default[] = wxT( "Default" );
// Initial values for netclass initialization
int NETCLASS::DEFAULT_CLEARANCE = DMils2iu( 100 ); // track to track and track to pads clearance
......
......@@ -80,7 +80,7 @@ protected:
public:
static const wxString Default; ///< the name of the default NETCLASS
static const wxChar Default[]; ///< the name of the default NETCLASS
/**
* Constructor
......
......@@ -41,37 +41,20 @@
#include <ratsnest_data.h>
// Helper class used to clean tracks and vias
class TRACKS_CLEANER : CONNECTIONS
class TRACKS_CLEANER: CONNECTIONS
{
private:
BOARD* m_Brd;
bool m_deleteUnconnectedTracks;
bool m_mergeSegments;
bool m_cleanVias;
BOARD * m_Brd;
public:
TRACKS_CLEANER( BOARD* aPcb );
TRACKS_CLEANER( BOARD * aPcb );
/**
* the cleanup function.
* return true if some item was modified
*/
bool CleanupBoard();
void SetdeleteUnconnectedTracksOpt( bool aDelete )
{
m_deleteUnconnectedTracks = aDelete;
}
void SetMergeSegmentsOpt( bool aMerge )
{
m_mergeSegments = aMerge;
}
void SetCleanViasOpt( bool aClean )
{
m_cleanVias = aClean;
}
bool CleanupBoard(PCB_EDIT_FRAME *aFrame, bool aCleanVias,
bool aMergeSegments, bool aDeleteUnconnected);
private:
......@@ -89,7 +72,7 @@ private:
/**
* Merge colinear segments and remove null len segments
*/
bool clean_segments();
bool clean_segments();
/**
* helper function
......@@ -103,7 +86,8 @@ private:
* merge aTrackRef and aCandidate, when possible,
* i.e. when they are colinear, same width, and obviously same layer
*/
TRACK* mergeCollinearSegmentIfPossible( TRACK* aTrackRef, TRACK* aCandidate, int aEndType );
TRACK* mergeCollinearSegmentIfPossible( TRACK* aTrackRef,
TRACK* aCandidate, int aEndType );
};
/* Install the cleanup dialog frame to know what should be cleaned
......@@ -117,19 +101,9 @@ void PCB_EDIT_FRAME::Clean_Pcb()
wxBusyCursor( dummy );
TRACKS_CLEANER cleaner( GetBoard() );
cleaner.SetdeleteUnconnectedTracksOpt( dlg.m_deleteUnconnectedSegm );
cleaner.SetMergeSegmentsOpt( dlg.m_mergeSegments );
cleaner.SetCleanViasOpt( dlg.m_cleanVias );
if( cleaner.CleanupBoard() )
{
// Clear undo and redo lists to avoid inconsistencies between lists
GetScreen()->ClearUndoRedoList();
SetCurItem( NULL );
Compile_Ratsnest( NULL, true );
OnModify();
}
cleaner.CleanupBoard( this, dlg.m_cleanVias, dlg.m_mergeSegments,
dlg.m_deleteUnconnectedSegm );
m_canvas->Refresh( true );
}
......@@ -142,30 +116,38 @@ void PCB_EDIT_FRAME::Clean_Pcb()
* Create segments when track ends are incorrectly connected:
* i.e. when a track end covers a pad or a via but is not exactly on the pad or the via center
*/
bool TRACKS_CLEANER::CleanupBoard()
bool TRACKS_CLEANER::CleanupBoard( PCB_EDIT_FRAME *aFrame,
bool aCleanVias,
bool aMergeSegments,
bool aDeleteUnconnected )
{
bool modified = false;
// delete redundant vias
if( m_cleanVias && clean_vias() )
modified = true;
modified |= (aCleanVias && clean_vias());
// Remove null segments and intermediate points on aligned segments
if( m_mergeSegments && clean_segments() )
modified = true;
modified |= (aMergeSegments && clean_segments());
// Delete dangling tracks
if( m_deleteUnconnectedTracks && deleteUnconnectedTracks() )
modified = true;
modified |= (aDeleteUnconnected && deleteUnconnectedTracks());
if( modified )
{
// Clear undo and redo lists to avoid inconsistencies between lists
// XXX This is very involved... maybe a member in PCB_EDIT_FRAME
// would be better?
aFrame->GetScreen()->ClearUndoRedoList();
aFrame->SetCurItem( NULL );
aFrame->Compile_Ratsnest( NULL, true );
aFrame->OnModify();
}
return modified;
}
TRACKS_CLEANER::TRACKS_CLEANER( BOARD* aPcb ) : CONNECTIONS( aPcb )
TRACKS_CLEANER::TRACKS_CLEANER( BOARD * aPcb ): CONNECTIONS( aPcb )
{
m_Brd = aPcb;
m_deleteUnconnectedTracks = false;
m_mergeSegments = false;
// Build connections info
BuildPadsList();
......@@ -177,22 +159,22 @@ void TRACKS_CLEANER::buildTrackConnectionInfo()
BuildTracksCandidatesList( m_Brd->m_Track, NULL);
// clear flags and variables used in cleanup
for( TRACK* track = m_Brd->m_Track; track; track = track->Next() )
for( TRACK * track = m_Brd->m_Track; track; track = track->Next() )
{
track->start = NULL;
track->end = NULL;
track->m_PadsConnected.clear();
track->SetState( START_ON_PAD | END_ON_PAD | BUSY, false );
track->SetState( START_ON_PAD|END_ON_PAD|BUSY, false );
}
// Build connections info tracks to pads
SearchTracksConnectedToPads();
for( TRACK* track = m_Brd->m_Track; track; track = track->Next() )
for( TRACK * track = m_Brd->m_Track; track; track = track->Next() )
{
// Mark track if connected to pads
for( unsigned jj = 0; jj < track->m_PadsConnected.size(); jj++ )
{
D_PAD* pad = track->m_PadsConnected[jj];
D_PAD * pad = track->m_PadsConnected[jj];
if( pad->HitTest( track->GetStart() ) )
{
......@@ -211,7 +193,6 @@ void TRACKS_CLEANER::buildTrackConnectionInfo()
bool TRACKS_CLEANER::clean_vias()
{
TRACK* next_track;
bool modified = false;
for( TRACK* track = m_Brd->m_Track; track; track = track->Next() )
......@@ -229,6 +210,7 @@ bool TRACKS_CLEANER::clean_vias()
// Search and delete others vias at same location
TRACK* alt_track = track->Next();
TRACK* next_track;
for( ; alt_track != NULL; alt_track = next_track )
{
next_track = alt_track->Next();
......@@ -249,6 +231,7 @@ bool TRACKS_CLEANER::clean_vias()
}
// Delete Via on pads at same location
TRACK* next_track;
for( TRACK* track = m_Brd->m_Track; track != NULL; track = next_track )
{
next_track = track->Next();
......@@ -260,9 +243,9 @@ bool TRACKS_CLEANER::clean_vias()
// if one pad through is found, the via can be removed
for( unsigned ii = 0; ii < track->m_PadsConnected.size(); ii++ )
{
D_PAD* pad = track->m_PadsConnected[ii];
D_PAD * pad = track->m_PadsConnected[ii];
if( ( pad->GetLayerMask() & ALL_CU_LAYERS ) == ALL_CU_LAYERS )
if( (pad->GetLayerMask() & ALL_CU_LAYERS) == ALL_CU_LAYERS )
{
// redundant: via delete it
m_Brd->GetRatsnest()->Remove( track );
......@@ -295,8 +278,7 @@ bool TRACKS_CLEANER::deleteUnconnectedTracks()
{
item_erased = false;
TRACK* next_track;
for( TRACK* track = m_Brd->m_Track; track ; track = next_track )
for( TRACK * track = m_Brd->m_Track; track ; track = next_track )
{
next_track = track->Next();
......@@ -317,7 +299,7 @@ bool TRACKS_CLEANER::deleteUnconnectedTracks()
LAYER_NUM top_layer, bottom_layer;
ZONE_CONTAINER* zone;
if( ( type_end & START_ON_PAD ) == 0 )
if( (type_end & START_ON_PAD ) == 0 )
{
TRACK* other = track->GetTrace( m_Brd->m_Track, NULL, FLG_START );
......@@ -339,7 +321,7 @@ bool TRACKS_CLEANER::deleteUnconnectedTracks()
}
}
if( ( other == NULL ) && ( zone == NULL ) )
if( (other == NULL) && (zone == NULL) )
{
flag_erase |= 1;
}
......@@ -427,7 +409,7 @@ bool TRACKS_CLEANER::deleteUnconnectedTracks()
via->GetNetCode() );
}
if( ( other == NULL ) && ( zone == NULL ) )
if( (other == NULL) && (zone == NULL) )
flag_erase |= 0x20;
track->SetState( BUSY, false );
......@@ -459,8 +441,6 @@ bool TRACKS_CLEANER::clean_segments()
bool modified = false;
TRACK* segment, * nextsegment;
TRACK* other;
int flag, no_inc;
// Delete null segments
for( segment = m_Brd->m_Track; segment; segment = nextsegment )
......@@ -472,6 +452,7 @@ bool TRACKS_CLEANER::clean_segments()
m_Brd->GetRatsnest()->Remove( segment );
segment->ViewRelease();
segment->DeleteStructure();
modified = true;
}
}
......@@ -524,7 +505,8 @@ bool TRACKS_CLEANER::clean_segments()
if( segment->Type() != PCB_TRACE_T )
continue;
flag = no_inc = 0;
unsigned flag = 0;
bool no_inc = false;
// search for a possible point connected to the START point of the current segment
for( segStart = segment->Next(); ; )
......@@ -603,7 +585,7 @@ bool TRACKS_CLEANER::clean_segments()
if( segDelete )
{
no_inc = 1;
no_inc = true;
m_Brd->GetRatsnest()->Remove( segDelete );
segDelete->ViewRelease();
segDelete->DeleteStructure();
......
......@@ -91,7 +91,7 @@ void PCB_EDIT_FRAME::InstallNetlistFrame( wxDC* DC )
// was: wxGetApp().WriteProjectConfig( fn.GetFullPath(), GROUP, GetProjectFileParameters() );
Prj().ConfigSave( Kiface().KifaceSearch(), fn.GetFullPath(),
GROUP, GetProjectFileParameters() );
GROUP_PCB, GetProjectFileParameters() );
}
}
......@@ -426,7 +426,7 @@ bool DIALOG_NETLIST::verifyFootprints( const wxString& aNetlistFilename,
std::auto_ptr< NETLIST_READER > nlr( netlistReader );
netlistReader->LoadNetlist();
}
catch( IO_ERROR& ioe )
catch( const IO_ERROR& ioe )
{
msg.Printf( _( "Error loading netlist file:\n%s" ), ioe.errorText.GetData() );
wxMessageBox( msg, _( "Netlist Load Error" ), wxOK | wxICON_ERROR );
......
......@@ -403,7 +403,7 @@ bool Export_IDF3( BOARD* aPcb, const wxString& aFullFileName, double aUseThou )
idfBoard.Finish();
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
wxLogDebug( wxT( "An error occurred attemping export to IDFv3.\n\nError: %s" ),
GetChars( ioe.errorText ) );
......
......@@ -713,7 +713,7 @@ bool PCB_EDIT_FRAME::DoGenFootprintsReport( const wxString& aFullFilename, bool
fprintf( rptfile, "$EndMODULE %s\n\n", TO_UTF8 (Module->GetReference() ) );
}
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
DisplayError( NULL, ioe.errorText );
}
......
......@@ -404,7 +404,7 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
SetBoard( loadedBoard );
}
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
wxString msg = wxString::Format( _( "Error loading board.\n%s" ),
ioe.errorText.GetData() );
......@@ -692,7 +692,7 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupF
pi->Save( pcbFileName.GetFullPath(), GetBoard(), NULL );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
wxString msg = wxString::Format( _( "Error saving board.\n%s" ),
ioe.errorText.GetData() );
......
......@@ -570,7 +570,7 @@ int main( int argc, char** argv )
printf("[%d]:%s\n", i, TO_UTF8( fps[i] ) );
}
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
printf( "%s\n", TO_UTF8(ioe.errorText) );
}
......
......@@ -204,7 +204,7 @@ public:
* or
* IO_MGR::Save(...);
* }
* catch( IO_ERROR ioe )
* catch( const IO_ERROR& ioe )
* {
* // grab text from ioe, show in error window.
* }
......
/**
* @file ioascii.cpp
* @brief Routines for reading and saving of structures in ASCII file common to Pcbnew and CvPcb.
*/
#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>
/**
* @todo Fix having to recompile the same file with a different defintion. This is
* what C++ derivation was designed to solve.
*/
#ifdef PCBNEW
#include <zones.h>
#endif
#ifdef CVPCB
#include <cvpcb.h>
#endif
#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>
/* ASCII format of structures:
*
* Structure PAD:
*
* $PAD
* Sh "name" form DIMVA dimH dV dH East: general form dV, dH = delta size
* Dr. diam dV dH: drill: diameter drilling offsets
* At Type S / N layers: standard, cms, conn, hole, meca.,
* Stack / Normal, 32-bit hexadecimal: occupation layers
* Nm net_code netname
* Po posrefX posrefy: reFX position, Y (0 = east position / anchor)
* $EndPAD
*
* Module Structure
*
* $MODULE namelib
* Po ax ay east layer masquelayer m_TimeCode
* ax ay ord = anchor (position module)
* east = east to 0.1 degree
* layer = layer number
* masquelayer = silkscreen layer for
* m_TimeCode internal use (groups)
* Li <namelib>
*
* Cd <text> description of the component (Component Doc)
* Kw <text> List of key words
*
* Sc schematic timestamp, reference schematic
*
* Op rot90 rot180 placement Options Auto (court rot 90, 180)
* rot90 is about 2x4-bit:
* lsb = cost rot 90, rot court msb = -90;
*
* Tn px py DIMVA dimh East thickness mirror visible "text"
* n = type (0 = ref, val = 1,> 1 = qcq
* Texts POS x, y / anchor and orient module 0
* DIMVA dimh East
* mirror thickness (Normal / Mirror)
* Visible V / I
* DS ox oy fx fy w
* Edge: coord segment ox, oy has fx, fy, on
* was the anchor and orient 0
* thickness w
* DC ox oy fx fy w descr circle (center, 1 point, thickness)
* $PAD
* $EndPAD section pads if available
* $Endmodule
*/
/// Get the length of a string constant, at compile time
#define SZ( x ) (sizeof(x)-1)
static int NbDraw, NbTrack, NbZone, NbMod, NbNets;
static const char delims[] = " =\n\r";
/** Read a list of segments (Tracks, zones)
* @return items count or - count if no end block ($End...) found.
*/
int PCB_BASE_FRAME::ReadListeSegmentDescr( LINE_READER* aReader,
TRACK* insertBeforeMe,
int StructType,
int NumSegm )
{
int shape, width, drill, layer, type, flags, net_code;
int tempStartX, tempStartY;
int tempEndX, tempEndY;
int ii = 0;
TRACK* newTrack;
while( aReader->ReadLine() )
{
char* line = aReader->Line();
int makeType;
unsigned long timeStamp;
if( line[0] == '$' )
{
return ii; // end of segmentlist: OK
}
int arg_count = sscanf( line + 2, " %d %d %d %d %d %d %d", &shape,
&tempStartX, &tempStartY,
&tempEndX, &tempEndY, &width,
&drill );
// Read the 2nd line to determine the exact type, one of:
// PCB_TRACE_T, PCB_VIA_T, or PCB_ZONE_T. The type field in 2nd line
// differentiates between PCB_TRACE_T and PCB_VIA_T. With virtual
// functions in use, it is critical to instantiate the PCB_VIA_T
// exactly.
if( !aReader->ReadLine() )
break;
line = aReader->Line();
if( line[0] == '$' )
break;
// parse the 2nd line first to determine the type of object
sscanf( line + 2, " %d %d %d %lX %X", &layer, &type, &net_code,
&timeStamp, &flags );
if( StructType==PCB_TRACE_T && type==1 )
makeType = PCB_VIA_T;
else
makeType = StructType;
switch( makeType )
{
default:
case PCB_TRACE_T:
newTrack = new TRACK( GetBoard() );
GetBoard()->m_Track.Insert( newTrack, insertBeforeMe );
break;
case PCB_VIA_T:
newTrack = new SEGVIA( GetBoard() );
GetBoard()->m_Track.Insert( newTrack, insertBeforeMe );
break;
case PCB_ZONE_T: // this is now deprecated, but exist in old boards
newTrack = new SEGZONE( GetBoard() );
GetBoard()->m_Zone.Insert( (SEGZONE*) newTrack, (SEGZONE*) insertBeforeMe );
break;
}
newTrack->SetTimeStamp( timeStamp );
newTrack->m_Start.x = tempStartX;
newTrack->m_Start.y = tempStartY;
newTrack->m_End.x = tempEndX;
newTrack->m_End.y = tempEndY;
newTrack->m_Width = width;
newTrack->m_Shape = shape;
if( arg_count < 7 || drill <= 0 )
newTrack->SetDrillDefault();
else
newTrack->SetDrill( drill );
newTrack->SetLayer( layer );
if( makeType == PCB_VIA_T ) // Ensure layers are OK when possible:
{
if( newTrack->GetShape() == VIA_THROUGH )
( (SEGVIA*) newTrack )->SetLayerPair( LAYER_N_FRONT, LAYER_N_BACK );
}
newTrack->SetNet( net_code );
newTrack->SetState( flags, ON );
}
DisplayError( this, _( "Error: Unexpected end of file !" ) );
return -ii;
}
int PCB_BASE_FRAME::ReadGeneralDescrPcb( LINE_READER* aReader )
{
while( aReader->ReadLine() )
{
char* line = aReader->Line();
char* data = strtok( line, delims );
if( strnicmp( data, "$EndGENERAL", 10 ) == 0 )
break;
if( stricmp( data, "EnabledLayers" ) == 0 )
{
int enabledLayers = 0;
data = strtok( NULL, delims );
sscanf( data, "%X", &enabledLayers );
// layer usage
GetBoard()->SetEnabledLayers( enabledLayers );
// layer visibility equals layer usage, unless overridden later via "VisibleLayers"
GetBoard()->SetVisibleLayers( enabledLayers );
continue;
}
if( stricmp( data, "VisibleLayers" ) == 0 )
{
int visibleLayers = -1;
data = strtok( NULL, delims );
sscanf( data, "%X", &visibleLayers );
GetBoard()->SetVisibleLayers( visibleLayers );
continue;
}
if( strncmp( data, "Ly", 2 ) == 0 ) // Old format for Layer count
{
int Masque_Layer = 1, ii;
data = strtok( NULL, delims );
sscanf( data, "%X", &Masque_Layer );
// Setup layer count
int layer_count = 0;
for( ii = 0; ii < NB_COPPER_LAYERS; ii++ )
{
if( Masque_Layer & 1 )
layer_count++;
Masque_Layer >>= 1;
}
GetBoard()->SetCopperLayerCount( layer_count );
continue;
}
if( stricmp( data, "BoardThickness" ) == 0 )
{
data = strtok( NULL, delims );
GetBoard()->GetDesignSettings().m_BoardThickness = atoi( data );
continue;
}
if( strnicmp( data, "Links", 5 ) == 0 )
{
// Info only, do nothing
continue;
}
if( strnicmp( data, "NoConn", 6 ) == 0 )
{
data = strtok( NULL, delims );
GetBoard()->m_NbNoconnect = atoi( data );
continue;
}
if( strnicmp( data, "Di", 2 ) == 0 )
{
data = strtok( NULL, delims );
int x1 = atoi( data );
data = strtok( NULL, delims );
int y1 = atoi( data );
data = strtok( NULL, delims );
int x2 = atoi( data );
data = strtok( NULL, delims );
int y2 = atoi( data );
EDA_RECT bbbox( wxPoint( x1, y1 ), wxSize( x2-x1, y2-y1 ) );
GetBoard()->SetBoundingBox( bbbox );
continue;
}
// Read the number of segments of type DRAW, TRACK, ZONE
if( stricmp( data, "Ndraw" ) == 0 )
{
data = strtok( NULL, delims );
NbDraw = atoi( data );
continue;
}
if( stricmp( data, "Ntrack" ) == 0 )
{
data = strtok( NULL, delims );
NbTrack = atoi( data );
continue;
}
if( stricmp( data, "Nzone" ) == 0 )
{
data = strtok( NULL, delims );
NbZone = atoi( data );
continue;
}
if( stricmp( data, "Nmodule" ) == 0 )
{
data = strtok( NULL, delims );
NbMod = atoi( data );
continue;
}
if( stricmp( data, "Nnets" ) == 0 )
{
data = strtok( NULL, delims );
NbNets = atoi( data );
continue;
}
}
return 1;
}
int PCB_BASE_FRAME::ReadSetup( LINE_READER* aReader )
{
char* data;
NETCLASS* netclass_default = GetBoard()->m_NetClasses.GetDefault();
ZONE_SETTINGS zoneInfo = GetBoard()->GetZoneSettings();
BOARD_DESIGN_SETTINGS bds = GetBoard()->GetDesignSettings();
while( aReader->ReadLine() )
{
char* line = aReader->Line();
if( strnicmp( line, "PcbPlotParams", 13 ) == 0 )
{
PCB_PLOT_PARAMS plot_opts;
PCB_PLOT_PARAMS_PARSER parser( &line[13], aReader->GetSource() );
try
{
plot_opts.Parse( &parser );
}
catch( IO_ERROR& e )
{
wxString msg;
msg.Printf( _( "Error reading PcbPlotParams from %s:\n%s" ),
aReader->GetSource().GetData(),
e.errorText.GetData() );
wxMessageBox( msg, _( "Open Board File" ), wxOK | wxICON_ERROR );
}
GetBoard()->SetPlotOptions( plot_opts );
continue;
}
strtok( line, delims );
data = strtok( NULL, delims );
if( stricmp( line, "$EndSETUP" ) == 0 )
{
// Until such time as the *.brd file does not have the
// global parameters:
// "TrackWidth", "TrackMinWidth", "ViaSize", "ViaDrill",
// "ViaMinSize", and "TrackClearence", put those same global
// values into the default NETCLASS until later board load
// code should override them. *.brd files which have been
// saved with knowledge of NETCLASSes will override these
// defaults, old boards will not.
//
// @todo: I expect that at some point we can remove said global
// parameters from the *.brd file since the ones in the
// default netclass serve the same purpose. If needed
// at all, the global defaults should go into a preferences
// file instead so they are there to start new board
// projects.
GetBoard()->m_NetClasses.GetDefault()->SetParams();
GetBoard()->SetDesignSettings( bds );
GetBoard()->SetZoneSettings( zoneInfo );
return 0;
}
if( stricmp( line, "AuxiliaryAxisOrg" ) == 0 )
{
int gx = 0, gy = 0;
gx = atoi( data );
data = strtok( NULL, delims );
if( data )
gy = atoi( data );
SetOriginAxisPosition( wxPoint( gx, gy ) );
continue;
}
#ifdef PCBNEW
if( stricmp( line, "Layers" ) == 0 )
{
int tmp;
sscanf( data, "%d", &tmp );
GetBoard()->SetCopperLayerCount( tmp );
continue;
}
const int LAYERKEYZ = sizeof("Layer[") - 1;
if( strncmp( line, "Layer[", LAYERKEYZ ) == 0 )
{
// parse:
// Layer[n] <a_Layer_name_with_no_spaces> <LAYER_T>
char* cp = line + LAYERKEYZ;
int layer = atoi( cp );
if( data )
{
wxString layerName = FROM_UTF8( data );
GetBoard()->SetLayerName( layer, layerName );
data = strtok( NULL, " \n\r" );
if( data )
{
LAYER_T type = LAYER::ParseType( data );
GetBoard()->SetLayerType( layer, type );
}
}
continue;
}
if( stricmp( line, "TrackWidth" ) == 0 ) // no more used
{
continue;
}
if( stricmp( line, "TrackWidthList" ) == 0 )
{
int tmp = atoi( data );
GetBoard()->m_TrackWidthList.push_back( tmp );
continue;
}
if( stricmp( line, "TrackClearence" ) == 0 )
{
netclass_default->SetClearance( atoi( data ) );
continue;
}
if( stricmp( line, "TrackMinWidth" ) == 0 )
{
bds.m_TrackMinWidth = atoi( data );
continue;
}
if( stricmp( line, "ZoneClearence" ) == 0 )
{
zoneInfo.m_ZoneClearance = atoi( data );
continue;
}
if( stricmp( line, "DrawSegmWidth" ) == 0 )
{
bds.m_DrawSegmentWidth = atoi( data );
continue;
}
if( stricmp( line, "EdgeSegmWidth" ) == 0 )
{
bds.m_EdgeSegmentWidth = atoi( data );
continue;
}
if( stricmp( line, "ViaSize" ) == 0 ) // no more used
{
continue;
}
if( stricmp( line, "ViaMinSize" ) == 0 )
{
bds.m_ViasMinSize = atoi( data );
continue;
}
if( stricmp( line, "MicroViaSize" ) == 0 ) // Not used
{
continue;
}
if( stricmp( line, "MicroViaMinSize" ) == 0 )
{
bds.m_MicroViasMinSize = atoi( data );
continue;
}
if( stricmp( line, "ViaSizeList" ) == 0 )
{
int tmp = atoi( data );
VIA_DIMENSION via_dim;
via_dim.m_Diameter = tmp;
data = strtok( NULL, " \n\r" );
if( data )
{
tmp = atoi( data );
via_dim.m_Drill = tmp > 0 ? tmp : 0;
}
GetBoard()->m_ViasDimensionsList.push_back( via_dim );
continue;
}
if( stricmp( line, "ViaDrill" ) == 0 )
{
int diameter = atoi( data );
netclass_default->SetViaDrill( diameter );
continue;
}
if( stricmp( line, "ViaMinDrill" ) == 0 )
{
bds.m_ViasMinDrill = atoi( data );
continue;
}
if( stricmp( line, "MicroViaDrill" ) == 0 )
{
int diameter = atoi( data );
netclass_default->SetuViaDrill( diameter );
continue;
}
if( stricmp( line, "MicroViaMinDrill" ) == 0 )
{
int diameter = atoi( data );
bds.m_MicroViasMinDrill = diameter;
continue;
}
if( stricmp( line, "MicroViasAllowed" ) == 0 )
{
bds.m_MicroViasAllowed = atoi( data );
continue;
}
if( stricmp( line, "TextPcbWidth" ) == 0 )
{
bds.m_PcbTextWidth = atoi( data );
continue;
}
if( stricmp( line, "TextPcbSize" ) == 0 )
{
bds.m_PcbTextSize.x = atoi( data );
data = strtok( NULL, delims );
bds.m_PcbTextSize.y = atoi( data );
continue;
}
if( stricmp( line, "EdgeModWidth" ) == 0 )
{
bds.m_ModuleSegmentWidth = atoi( data );
continue;
}
if( stricmp( line, "TextModWidth" ) == 0 )
{
bds.m_ModuleTextWidth = atoi( data );
continue;
}
if( stricmp( line, "TextModSize" ) == 0 )
{
bds.m_ModuleTextSize.x = atoi( data );
data = strtok( NULL, delims );
bds.m_ModuleTextSize.y = atoi( data );
continue;
}
if( stricmp( line, "PadSize" ) == 0 )
{
int x = atoi( data );
data = strtok( NULL, delims );
int y = atoi( data );
bds.m_Pad_Master.SetSize( wxSize( x, y ) );
continue;
}
if( stricmp( line, "PadDrill" ) == 0 )
{
int sz = atoi( data );
bds.m_Pad_Master.SetSize( wxSize( sz, sz ) );
continue;
}
if( stricmp( line, "Pad2MaskClearance" ) == 0 )
{
bds.m_SolderMaskMargin = atoi( data );
continue;
}
if( stricmp( line, "Pad2PasteClearance" ) == 0 )
{
bds.m_SolderPasteMargin = atoi( data );
continue;
}
if( stricmp( line, "Pad2PasteClearanceRatio" ) == 0 )
{
bds.m_SolderPasteMarginRatio = atof( data );
continue;
}
if( stricmp( line, "GridOrigin" ) == 0 )
{
int Ox = 0;
int Oy = 0;
Ox = atoi( data );
data = strtok( NULL, delims );
if ( data )
Oy = atoi( data );
GetScreen()->m_GridOrigin.x = Ox;
GetScreen()->m_GridOrigin.y = Oy;
continue;
}
if( stricmp( line, "VisibleElements" ) == 0 )
{
int visibleElements = strtoul( data, 0, 16 );
bds.SetVisibleElements( visibleElements );
continue;
}
#endif
}
/* Ensure tracks and vias sizes lists are ok:
* Sort lists by by increasing value and remove duplicates
* (the first value is not tested, because it is the netclass value
*/
sort( GetBoard()->m_ViasDimensionsList.begin() + 1, GetBoard()->m_ViasDimensionsList.end() );
sort( GetBoard()->m_TrackWidthList.begin() + 1, GetBoard()->m_TrackWidthList.end() );
for( unsigned ii = 1; ii < GetBoard()->m_ViasDimensionsList.size() - 1; ii++ )
{
if( GetBoard()->m_ViasDimensionsList[ii] == GetBoard()->m_ViasDimensionsList[ii + 1] )
{
GetBoard()->m_ViasDimensionsList.erase( GetBoard()->m_ViasDimensionsList.begin() + ii );
ii--;
}
}
for( unsigned ii = 1; ii < GetBoard()->m_TrackWidthList.size() - 1; ii++ )
{
if( GetBoard()->m_TrackWidthList[ii] == GetBoard()->m_TrackWidthList[ii + 1] )
{
GetBoard()->m_TrackWidthList.erase( GetBoard()->m_TrackWidthList.begin() + ii );
ii--;
}
}
return 1;
}
#ifdef PCBNEW
static int WriteSetup( FILE* aFile, PCB_EDIT_FRAME* aFrame, BOARD* aBoard )
{
const BOARD_DESIGN_SETTINGS& bds = aBoard->GetDesignSettings();
NETCLASS* netclass_default = aBoard->m_NetClasses.GetDefault();
char text[1024];
fprintf( aFile, "$SETUP\n" );
sprintf( text, "InternalUnit %f INCH\n", 1.0 / PCB_INTERNAL_UNIT );
fprintf( aFile, "%s", text );
fprintf( aFile, "Layers %d\n", aBoard->GetCopperLayerCount() );
unsigned layerMask = g_TabAllCopperLayerMask[aBoard->GetCopperLayerCount() - 1];
for( int layer = 0; layerMask; ++layer, layerMask >>= 1 )
{
if( layerMask & 1 )
{
fprintf( aFile, "Layer[%d] %s %s\n", layer,
TO_UTF8( aBoard->GetLayerName( layer ) ),
LAYER::ShowType( aBoard->GetLayerType( layer ) ) );
}
}
// Save current default track width, for compatibility with older Pcbnew version;
fprintf( aFile, "TrackWidth %d\n", aBoard->GetCurrentTrackWidth() );
// Save custom tracks width list (the first is not saved here: this is the netclass value
for( unsigned ii = 1; ii < aBoard->m_TrackWidthList.size(); ii++ )
fprintf( aFile, "TrackWidthList %d\n", aBoard->m_TrackWidthList[ii] );
fprintf( aFile, "TrackClearence %d\n", netclass_default->GetClearance() );
fprintf( aFile, "ZoneClearence %d\n", aBoard->GetZoneSettings().m_ZoneClearance );
fprintf( aFile, "TrackMinWidth %d\n", bds.m_TrackMinWidth );
fprintf( aFile, "DrawSegmWidth %d\n", bds.m_DrawSegmentWidth );
fprintf( aFile, "EdgeSegmWidth %d\n", bds.m_EdgeSegmentWidth );
// Save current default via size, for compatibility with older Pcbnew version;
fprintf( aFile, "ViaSize %d\n", netclass_default->GetViaDiameter() );
fprintf( aFile, "ViaDrill %d\n", netclass_default->GetViaDrill() );
fprintf( aFile, "ViaMinSize %d\n", bds.m_ViasMinSize );
fprintf( aFile, "ViaMinDrill %d\n", bds.m_ViasMinDrill );
// Save custom vias diameters list (the first is not saved here: this is
// the netclass value
for( unsigned ii = 1; ii < aBoard->m_ViasDimensionsList.size(); ii++ )
fprintf( aFile, "ViaSizeList %d %d\n",
aBoard->m_ViasDimensionsList[ii].m_Diameter,
aBoard->m_ViasDimensionsList[ii].m_Drill );
// for old versions compatibility:
fprintf( aFile, "MicroViaSize %d\n", netclass_default->GetuViaDiameter() );
fprintf( aFile, "MicroViaDrill %d\n", netclass_default->GetuViaDrill() );
fprintf( aFile,
"MicroViasAllowed %d\n",
bds.m_MicroViasAllowed );
fprintf( aFile,
"MicroViaMinSize %d\n",
bds.m_MicroViasMinSize );
fprintf( aFile,
"MicroViaMinDrill %d\n",
bds.m_MicroViasMinDrill );
fprintf( aFile, "TextPcbWidth %d\n", bds.m_PcbTextWidth );
fprintf( aFile,
"TextPcbSize %d %d\n",
bds.m_PcbTextSize.x,
bds.m_PcbTextSize.y );
fprintf( aFile, "EdgeModWidth %d\n", bds.m_ModuleSegmentWidth );
fprintf( aFile, "TextModSize %d %d\n", bds.m_ModuleTextSize.x, bds.m_ModuleTextSize.y );
fprintf( aFile, "TextModWidth %d\n", bds.m_ModuleTextWidth );
fprintf( aFile, "PadSize %d %d\n", bds.m_Pad_Master.GetSize().x,
bds.m_Pad_Master.GetSize().y );
fprintf( aFile, "PadDrill %d\n", bds.m_Pad_Master.GetDrillSize().x );
fprintf( aFile,
"Pad2MaskClearance %d\n",
bds.m_SolderMaskMargin );
if( bds.m_SolderPasteMargin != 0 )
fprintf( aFile,
"Pad2PasteClearance %d\n",
bds.m_SolderPasteMargin );
if( bds.m_SolderPasteMarginRatio != 0 )
fprintf( aFile,
"Pad2PasteClearanceRatio %g\n",
bds.m_SolderPasteMarginRatio );
if ( aFrame->GetScreen()->m_GridOrigin != wxPoint( 0, 0 ) )
{
fprintf( aFile,
"GridOrigin %d %d\n",
aFrame->GetScreen()->m_GridOrigin.x,
aFrame->GetScreen()->m_GridOrigin.y );
}
fprintf( aFile,
"AuxiliaryAxisOrg %d %d\n",
aFrame->GetOriginAxisPosition().x,
aFrame->GetOriginAxisPosition().y );
fprintf( aFile, "VisibleElements %X\n", bds.GetVisibleElements() );
STRING_FORMATTER sf;
aBoard->GetPlotOptions().Format( &sf, 0 );
wxString record = FROM_UTF8( sf.GetString().c_str() );
record.Replace( wxT("\n"), wxT(""), true );
record.Replace( wxT(" "), wxT(" "), true);
fprintf( aFile, "PcbPlotParams %s\n", TO_UTF8( record ) );
fprintf( aFile, "$EndSETUP\n\n" );
return 1;
}
#endif
bool PCB_EDIT_FRAME::WriteGeneralDescrPcb( FILE* File )
{
EDA_ITEM* PtStruct = GetBoard()->m_Modules;
int NbModules, NbDrawItem, NbLayers;
// Write copper layer count
NbLayers = GetBoard()->GetCopperLayerCount();
fprintf( File, "$GENERAL\n" );
fprintf( File, "encoding utf-8\n");
fprintf( File, "LayerCount %d\n", NbLayers );
// Write old format for Layer count (for compatibility with old versions of
// pcbnew
fprintf( File,
"Ly %8X\n",
g_TabAllCopperLayerMask[NbLayers - 1] | ALL_NO_CU_LAYERS );
fprintf( File, "EnabledLayers %08X\n", GetBoard()->GetEnabledLayers() );
if( GetBoard()->GetEnabledLayers() != GetBoard()->GetVisibleLayers() )
fprintf( File, "VisibleLayers %08X\n", GetBoard()->GetVisibleLayers() );
fprintf( File, "Links %d\n", GetBoard()->GetRatsnestsCount() );
fprintf( File, "NoConn %d\n", GetBoard()->m_NbNoconnect );
// Write board's bounding box info
EDA_RECT bbbox = GetBoard()->ComputeBoundingBox();
fprintf( File, "Di %d %d %d %d\n",
bbbox.GetX(),
bbbox.GetY(),
bbbox.GetRight(),
bbbox.GetBottom() );
// Write segment count for footprints, drawings, track and zones
// Calculate the footprint count
for( NbModules = 0; PtStruct != NULL; PtStruct = PtStruct->Next() )
NbModules++;
PtStruct = GetBoard()->m_Drawings; NbDrawItem = 0;
for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
NbDrawItem++;
fprintf( File, "Ndraw %d\n", NbDrawItem );
fprintf( File, "Ntrack %d\n", GetBoard()->GetNumSegmTrack() );
fprintf( File, "Nzone %d\n", GetBoard()->GetNumSegmZone() );
fprintf( File, "BoardThickness %d\n", GetBoard()->GetDesignSettings().m_BoardThickness );
fprintf( File, "Nmodule %d\n", NbModules );
fprintf( File, "Nnets %d\n", GetBoard()->GetNetCount() );
fprintf( File, "$EndGENERAL\n\n" );
return true;
}
/**
* Function WriteSheetDescr
* Save the page information (size, texts, date ..)
* @param aPageSettings The page settings to write to \a aFile.
* @param aTitleBlock The title block information to write to \a aFile.
* @param aFile An open FILE to write info.
*/
static bool WriteSheetDescr( const PAGE_INFO& aPageSettings, const TITLE_BLOCK& aTitleBlock,
FILE* aFile )
{
fprintf( aFile, "$SHEETDESCR\n" );
fprintf( aFile, "Sheet %s %d %d%s\n",
TO_UTF8( aPageSettings.GetType() ),
aPageSettings.GetWidthMils(),
aPageSettings.GetHeightMils(),
!aPageSettings.IsCustom() && aPageSettings.IsPortrait() ?
" portrait" : ""
);
fprintf( aFile, "Title %s\n", EscapedUTF8( aTitleBlock.GetTitle() ).c_str() );
fprintf( aFile, "Date %s\n", EscapedUTF8( aTitleBlock.GetDate() ).c_str() );
fprintf( aFile, "Rev %s\n", EscapedUTF8( aTitleBlock.GetRevision() ).c_str() );
fprintf( aFile, "Comp %s\n", EscapedUTF8( aTitleBlock.GetCompany() ).c_str() );
fprintf( aFile, "Comment1 %s\n", EscapedUTF8( aTitleBlock.GetComment1() ).c_str() );
fprintf( aFile, "Comment2 %s\n", EscapedUTF8( aTitleBlock.GetComment2() ).c_str() );
fprintf( aFile, "Comment3 %s\n", EscapedUTF8( aTitleBlock.GetComment3() ).c_str() );
fprintf( aFile, "Comment4 %s\n", EscapedUTF8( aTitleBlock.GetComment4() ).c_str() );
fprintf( aFile, "$EndSHEETDESCR\n\n" );
return true;
}
#if !defined( USE_NEW_PCBNEW_LOAD )
static bool ReadSheetDescr( BOARD* aBoard, LINE_READER* aReader )
{
char buf[1024];
TITLE_BLOCK tb;
while( aReader->ReadLine() )
{
char* line = aReader->Line();
if( strnicmp( line, "$End", 4 ) == 0 )
{
aBoard->SetTitleBlock( tb );
return true;
}
if( strnicmp( line, "Sheet", 4 ) == 0 )
{
// e.g. "Sheet A3 16535 11700"
// width and height are in 1/1000th of an inch, always
PAGE_INFO page;
char* sname = strtok( line + SZ( "Sheet" ), delims );
if( sname )
{
wxString wname = FROM_UTF8( sname );
if( !page.SetType( wname ) )
{
/* this entire file is soon to be deleted.
m_error.Printf( _( "Unknown sheet type '%s' on line:%d" ),
wname.GetData(), m_reader->LineNumber() );
THROW_IO_ERROR( m_error );
*/
}
char* width = strtok( NULL, delims );
char* height = strtok( NULL, delims );
char* orient = strtok( NULL, delims );
// only keep width and height if page size is "User"
if( wname == PAGE_INFO::Custom )
{
if( width && height )
{
// legacy disk file describes paper in mils
// (1/1000th of an inch)
int w = atoi( width );
int h = atoi( height );
page.SetWidthMils( w );
page.SetHeightMils( h );
}
}
if( orient && !strcmp( orient, "portrait" ) )
{
page.SetPortrait( true );
}
aBoard->SetPageSettings( page );
}
continue;
}
if( strnicmp( line, "Title", 2 ) == 0 )
{
ReadDelimitedText( buf, line, 256 );
tb.SetTitle( FROM_UTF8( buf ) );
continue;
}
if( strnicmp( line, "Date", 2 ) == 0 )
{
ReadDelimitedText( buf, line, 256 );
tb.SetDate( FROM_UTF8( buf ) );
continue;
}
if( strnicmp( line, "Rev", 2 ) == 0 )
{
ReadDelimitedText( buf, line, 256 );
tb.SetRevision( FROM_UTF8( buf ) );
continue;
}
if( strnicmp( line, "Comp", 4 ) == 0 )
{
ReadDelimitedText( buf, line, 256 );
tb.SetCompany( FROM_UTF8( buf ) );
continue;
}
if( strnicmp( line, "Comment1", 8 ) == 0 )
{
ReadDelimitedText( buf, line, 256 );
tb.SetComment1( FROM_UTF8( buf ) );
continue;
}
if( strnicmp( line, "Comment2", 8 ) == 0 )
{
ReadDelimitedText( buf, line, 256 );
tb.SetComment2( FROM_UTF8( buf ) );
continue;
}
if( strnicmp( line, "Comment3", 8 ) == 0 )
{
ReadDelimitedText( buf, line, 256 );
tb.SetComment3( FROM_UTF8( buf ) );
continue;
}
if( strnicmp( line, "Comment4", 8 ) == 0 )
{
ReadDelimitedText( buf, line, 256 );
tb.SetComment4( FROM_UTF8( buf ) );
continue;
}
}
return false;
}
int PCB_EDIT_FRAME::ReadPcbFile( LINE_READER* aReader, bool Append )
{
wxBusyCursor dummy;
// Switch the locale to standard C (needed to read floating point numbers
// like 1.3)
SetLocaleTo_C_standard();
BOARD* board = GetBoard();
board->m_Status_Pcb = 0;
board->m_NetClasses.Clear();
// Put a dollar sign in front, and test for a specific length of characters
// The -1 is to omit the trailing \0 which is included in sizeof() on a
// string.
#define TESTLINE( x ) (strncmp( line, "$" x, sizeof("$" x) - 1 ) == 0)
while( aReader->ReadLine() )
{
char* line = aReader->Line();
// put the more frequent ones at the top
if( TESTLINE( "MODULE" ) )
{
MODULE* module = new MODULE( board );
board->Add( module, ADD_APPEND );
module->ReadDescr( aReader );
continue;
}
if( TESTLINE( "DRAWSEGMENT" ) )
{
DRAWSEGMENT* dseg = new DRAWSEGMENT( board );
board->Add( dseg, ADD_APPEND );
dseg->ReadDrawSegmentDescr( aReader );
continue;
}
if( TESTLINE( "EQUIPOT" ) )
{
NETINFO_ITEM* net = new NETINFO_ITEM( board );
board->m_NetInfo.AppendNet( net );
net->ReadDescr( aReader );
continue;
}
if( TESTLINE( "TEXTPCB" ) )
{
TEXTE_PCB* pcbtxt = new TEXTE_PCB( board );
board->Add( pcbtxt, ADD_APPEND );
pcbtxt->ReadTextePcbDescr( aReader );
continue;
}
if( TESTLINE( "TRACK" ) )
{
#ifdef PCBNEW
TRACK* insertBeforeMe = Append ? NULL : board->m_Track.GetFirst();
ReadListeSegmentDescr( aReader, insertBeforeMe, PCB_TRACE_T, NbTrack );
#endif
continue;
}
if( TESTLINE( "NCLASS" ) )
{
// create an empty NETCLASS without a name.
NETCLASS* netclass = new NETCLASS( board, wxEmptyString );
// fill it from the *.brd file, and establish its name.
netclass->ReadDescr( aReader );
if( !board->m_NetClasses.Add( netclass ) )
{
// Must have been a name conflict, this is a bad board file.
// User may have done a hand edit to the file.
// Delete netclass if board could not take ownership of it.
delete netclass;
// @todo: throw an exception here, this is a bad board file.
}
continue;
}
if( TESTLINE( "CZONE_OUTLINE" ) )
{
ZONE_CONTAINER* zone_descr = new ZONE_CONTAINER( board );
zone_descr->ReadDescr( aReader );
if( zone_descr->GetNumCorners() > 2 ) // should always occur
board->Add( zone_descr );
else
delete zone_descr;
continue;
}
if( TESTLINE( "COTATION" ) )
{
DIMENSION* dim = new DIMENSION( board );
board->Add( dim, ADD_APPEND );
dim->ReadDimensionDescr( aReader );
continue;
}
if( TESTLINE( "PCB_TARGET" ) || TESTLINE( "MIREPCB" ) )
{
PCB_TARGET* t = new PCB_TARGET( board );
board->Add( t, ADD_APPEND );
t->ReadMirePcbDescr( aReader );
continue;
}
if( TESTLINE( "ZONE" ) )
{
#ifdef PCBNEW
SEGZONE* insertBeforeMe = Append ? NULL : board->m_Zone.GetFirst();
ReadListeSegmentDescr( aReader, insertBeforeMe, PCB_ZONE_T, NbZone );
#endif
continue;
}
if( TESTLINE( "GENERAL" ) )
{
ReadGeneralDescrPcb( aReader );
continue;
}
if( TESTLINE( "SHEETDESCR" ) )
{
ReadSheetDescr( board, aReader );
continue;
}
if( TESTLINE( "SETUP" ) )
{
if( !Append )
{
ReadSetup( aReader );
}
else
{
while( aReader->ReadLine() )
{
line = aReader->Line();
if( TESTLINE( "EndSETUP" ) )
break;
}
}
continue;
}
if( TESTLINE( "EndPCB" ) )
break;
}
SetLocaleTo_Default(); // revert to the current locale
board->m_Status_Pcb = 0;
// Build the net info list
board->BuildListOfNets();
board->SynchronizeNetsAndNetClasses();
SetStatusText( wxEmptyString );
BestZoom();
return 1;
}
#endif
#ifdef PCBNEW
/* Save the current PCB in ASCII format
* Returns
* 1 if OK
* 0 if error occurs saving file.
*/
int PCB_EDIT_FRAME::SavePcbFormatAscii( FILE* aFile )
{
bool rc;
GetBoard()->m_Status_Pcb &= ~CONNEXION_OK;
wxBeginBusyCursor();
// Switch the locale to standard C (needed to print floating point numbers
// like 1.3)
LOCALE_IO toggle;
// Writing file header.
fprintf( aFile, "PCBNEW-BOARD Version %d date %s\n\n", LEGACY_BOARD_FILE_VERSION,
TO_UTF8( DateAndTime() ) );
fprintf( aFile, "# Created by Pcbnew%s\n\n", TO_UTF8( GetBuildVersion() ) );
GetBoard()->SynchronizeNetsAndNetClasses();
// Select default Netclass before writing file.
// Useful to save default values in headers
GetBoard()->SetCurrentNetClass( GetBoard()->m_NetClasses.GetDefault()->GetName() );
WriteGeneralDescrPcb( aFile );
WriteSheetDescr( GetBoard()->GetPageSettings(), GetBoard()->GetTitleBlock(), aFile );
WriteSetup( aFile, this, GetBoard() );
rc = GetBoard()->Save( aFile );
wxEndBusyCursor();
if( !rc )
DisplayError( this, wxT( "Unable to save PCB file" ) );
else
SetStatusText( wxEmptyString );
return rc;
}
#endif
/**
* @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>
#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 <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 1 || !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 < GetNetCount(); ii++ )
if( !FindNet( 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 %g %lX %X\n",
m_Layer, m_Type, GetAngle(),
m_TimeStamp, GetStatus() );
}
else
{
fprintf( aFile, "De %d %d %g %lX %X %d %d %d %d\n",
m_Layer, m_Type, GetAngle(),
m_TimeStamp, GetStatus(),
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;
fprintf( aFile, "$CZONE_OUTLINE\n" );
// Save the outline main info
ret = fprintf( aFile, "ZInfo %8.8lX %d %s\n",
m_TimeStamp, GetNet(),
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;
if( GetPriority() > 0 )
{
ret = fprintf( aFile, "ZPriority %d\n", GetPriority() );
if( ret < 1 )
return false;
}
// Save pad option and clearance
int padConnection;
switch( m_PadConnection )
{
default:
case PAD_IN_ZONE:
padConnection = 'I';
break;
case THERMAL_PAD:
padConnection = 'T';
break;
case PAD_NOT_IN_ZONE:
padConnection = 'X';
break;
}
ret = fprintf( aFile, "ZClearance %d %c\n", m_ZoneClearance, padConnection );
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 %g\n",
m_Pos.x, m_Pos.y, m_Size.x, m_Size.y, m_Thickness, GetOrientation() );
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 %g %d %d\n",
m_Start0.x, m_Start0.y,
m_End0.x, m_End0.y,
GetAngle(),
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<m_PolyPoints.size(); ++i )
fprintf( aFile, "Dl %d %d\n", m_PolyPoints[i].x, m_PolyPoints[i].y );
break;
default:
// future: throw an exception here
#if defined(DEBUG)
printf( "EDGE_MODULE::Save(): unexpected m_Shape: %d\n", m_Shape );
#endif
break;
}
return ret > 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, GetStatus() );
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.GetText().IsEmpty() )
fprintf( aFile, "Te %s\n", EscapedUTF8( m_Text.GetText() ).c_str() );
else
fprintf( aFile, "Te \"?\"\n" );
fprintf( aFile, "Po %d %d %d %d %d %g %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 %g\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( GetAttribute() )
{
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( GetDieLength() != 0 )
fprintf( aFile, "Le %d\n", GetDieLength() );
if( GetLocalSolderMaskMargin() != 0 )
fprintf( aFile, ".SolderMask %d\n", GetLocalSolderMaskMargin() );
if( GetLocalSolderPasteMargin() != 0 )
fprintf( aFile, ".SolderPaste %d\n", GetLocalSolderPasteMargin() );
if( GetLocalSolderPasteMarginRatio() != 0 )
fprintf( aFile, ".SolderPasteRatio %g\n", GetLocalSolderPasteMarginRatio() );
if( GetLocalClearance() != 0 )
fprintf( aFile, ".LocalClearance %d\n", GetLocalClearance() );
if( m_ZoneConnection != UNDEFINED_CONNECTION )
fprintf( aFile, ".ZoneConnection %d\n", m_ZoneConnection );
if( m_ThermalWidth != 0 )
fprintf( aFile, ".ThermalWidth %d\n", m_ThermalWidth );
if( m_ThermalGap != 0 )
fprintf( aFile, ".ThermalGap %d\n", m_ThermalGap );
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 %g %d %8.8lX %8.8lX %s\n",
m_Pos.x, m_Pos.y,
GetOrientation(), 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( GetLocalSolderMaskMargin() != 0 )
fprintf( aFile, ".SolderMask %d\n", GetLocalSolderMaskMargin() );
if( m_LocalSolderPasteMargin != 0 )
fprintf( aFile, ".SolderPaste %d\n", GetLocalSolderPasteMargin() );
if( GetLocalSolderPasteMarginRatio() != 0 )
fprintf( aFile, ".SolderPasteRatio %g\n", GetLocalSolderPasteMarginRatio() );
if( m_LocalClearance != 0 )
fprintf( aFile, ".LocalClearance %d\n", GetLocalClearance() );
if( m_ZoneConnection != UNDEFINED_CONNECTION )
fprintf( aFile, ".ZoneConnection %d\n", m_ZoneConnection );
if( m_ThermalWidth != 0 )
fprintf( aFile, ".ThermalWidth %d\n", m_ThermalWidth );
if( m_ThermalGap != 0 )
fprintf( aFile, ".ThermalGap %d\n", m_ThermalGap );
// 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 1 || !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 %lf",
BufCar, &m_Size.x, &m_Size.y,
&m_DeltaSize.x, &m_DeltaSize.y,
&m_Orient );
ll = 0xFF & BufCar[0];
// Read pad shape
PAD_SHAPE_T shape;
switch( ll )
{
default:
case 'C': shape = PAD_CIRCLE; break;
case 'R': shape = PAD_RECT; break;
case 'O': shape = PAD_OVAL; break;
case 'T': shape = PAD_TRAPEZOID; break;
}
SetShape( shape ); // sets m_boundingRadius = -1
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
SetAttribute( PAD_STANDARD );
if( strncmp( BufLine, "SMD", 3 ) == 0 )
SetAttribute( PAD_SMD );
if( strncmp( BufLine, "CONN", 4 ) == 0 )
SetAttribute( PAD_CONN );
if( strncmp( BufLine, "HOLE", 4 ) == 0 )
SetAttribute( 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 );
SetDieLength( lengthdie );
break;
case '.': // Read specific data
if( strnicmp( Line, ".SolderMask ", 12 ) == 0 )
SetLocalSolderMaskMargin( atoi( Line + 12 ) );
else if( strnicmp( Line, ".SolderPaste ", 13 ) == 0 )
SetLocalSolderPasteMargin( atoi( Line + 13 ) );
else if( strnicmp( Line, ".SolderPasteRatio ", 18 ) == 0 )
SetLocalSolderPasteMarginRatio( atoi( Line + 18 ) );
else if( strnicmp( Line, ".LocalClearance ", 16 ) == 0 )
SetLocalClearance( atoi( Line + 16 ) );
else if( strnicmp( Line, ".ZoneConnection ", 16 ) == 0 )
m_ZoneConnection = (ZoneConnection)atoi( Line + 16 );
else if( strnicmp( Line, ".ThermalWidth ", 14 ) == 0 )
m_ThermalWidth = atoi( Line + 14 );
else if( strnicmp( Line, ".ThermalGap ", 12 ) == 0 )
m_ThermalGap = atoi( Line + 12 );
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 );
wxPoint padpos = pad->GetPosition();
RotatePoint( &padpos, m_Orient );
pad->SetPosition( padpos + m_Pos );
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':
double orientation;
memset( BufCar1, 0, sizeof(BufCar1) );
sscanf( PtLine, "%d %d %lf %d %lX %lX %s",
&m_Pos.x, &m_Pos.y,
&orientation, &m_Layer,
&m_LastEdit_Time, &m_TimeStamp, BufCar1 );
SetOrientation( orientation );
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 )
SetLocalSolderMaskMargin( atoi( Line + 12 ) );
else if( strnicmp( Line, ".SolderPaste ", 13 ) == 0 )
SetLocalSolderPasteMargin( atoi( Line + 13 ) );
else if( strnicmp( Line, ".SolderPasteRatio ", 18 ) == 0 )
SetLocalSolderPasteMarginRatio( atof( Line + 18 ) );
else if( strnicmp( Line, ".LocalClearance ", 16 ) == 0 )
SetLocalClearance( atoi( Line + 16 ) );
else if( strnicmp( Line, ".ZoneConnection ", 16 ) == 0 )
m_ZoneConnection = (ZoneConnection)atoi( Line + 16 );
else if( strnicmp( Line, ".ThermalWidth ", 14 ) == 0 )
m_ThermalWidth = atoi( Line + 14 );
else if( strnicmp( Line, ".ThermalGap ", 12 ) == 0 )
m_ThermalGap = atoi( Line + 12 );
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:
double angle;
sscanf( Line + 3, "%d %d %d %d %lf %d %d",
&m_Start0.x, &m_Start0.y,
&m_End0.x, &m_End0.y,
&angle, &m_Width, &m_Layer );
NORMALIZE_ANGLE_360( angle );
SetAngle( 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; ii<pointCount; ii++ )
{
if( aReader->ReadLine() )
{
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:
double angle;
sscanf( token, "%lf", &angle );
SetAngle( 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
{
SetTimeStamp( ts );
SetNet( 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, "ZPriority", 9 ) == 0 )
{
int tmp = 0;
text = Line + 9;
ret = sscanf( text, "%d", &tmp );
if( ret < 1 )
return false;
SetPriority( tmp );
}
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_SETTINGS::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 padConnection;
text = Line + 10;
ret = sscanf( text, "%d %1c", &clearance, &padConnection );
if( ret < 2 )
{
error = true;
}
else
{
m_ZoneClearance = clearance;
switch( padConnection )
{
case 'i':
case 'I':
m_PadConnection = PAD_IN_ZONE;
break;
case 't':
case 'T':
m_PadConnection = THERMAL_PAD;
break;
case 'x':
case 'X':
m_PadConnection = 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, Mils2iu( m_Poly->GetDefaultHatchPitchMils() ) );
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 )
{
double angle;
sscanf( line + 2, " %d %d %d %d %d %lf",
&m_Pos.x, &m_Pos.y, &m_Size.x, &m_Size.y,
&m_Thickness, &angle );
SetOrientation( angle );
// 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();
double angle;
int layer = SILKSCREEN_N_FRONT;
BufCar1[0] = 0;
BufCar2[0] = 0;
BufCar3[0] = 0;
if( sscanf( line + 1, "%d %d %d %d %d %lf %d %s %s %d %s",
&type,
&m_Pos0.x, &m_Pos0.y,
&m_Size.y, &m_Size.x,
&angle, &m_Thickness,
BufCar1, BufCar2, &layer, BufCar3 ) >= 10 )
{
success = true;
SetOrientation( angle );
}
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
......@@ -199,7 +199,7 @@ MODULE* FOOTPRINT_EDIT_FRAME::Import_Module()
return NULL;
}
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
DisplayError( this, ioe.errorText );
return NULL;
......@@ -222,7 +222,7 @@ MODULE* FOOTPRINT_EDIT_FRAME::Import_Module()
return NULL;
}
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
DisplayError( this, ioe.errorText );
return NULL;
......@@ -259,7 +259,7 @@ MODULE* FOOTPRINT_EDIT_FRAME::Import_Module()
return NULL;
}
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
DisplayError( this, ioe.errorText );
return NULL;
......@@ -334,7 +334,7 @@ void FOOTPRINT_EDIT_FRAME::Export_Module( MODULE* aModule )
fprintf( fp, "%s", pcb_io.GetStringOutput( false ).c_str() );
fclose( fp );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
DisplayError( this, ioe.errorText );
return;
......@@ -357,7 +357,7 @@ bool FOOTPRINT_EDIT_FRAME::SaveCurrentModule( const wxString* aLibPath )
pi->FootprintSave( libPath, GetBoard()->m_Modules );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
DisplayError( this, ioe.errorText );
return false;
......@@ -429,7 +429,7 @@ wxString FOOTPRINT_EDIT_FRAME::CreateNewLibrary()
writable = pi->IsFootprintLibWritable( libPath );
exists = true; // no exception was thrown, lib must exist.
}
catch( IO_ERROR )
catch( const IO_ERROR& )
{
// ignore, original values of 'writable' and 'exists' are accurate.
}
......@@ -455,7 +455,7 @@ wxString FOOTPRINT_EDIT_FRAME::CreateNewLibrary()
pi->FootprintLibCreate( libPath );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
DisplayError( this, ioe.errorText );
return wxEmptyString;
......@@ -499,7 +499,7 @@ bool FOOTPRINT_EDIT_FRAME::DeleteModuleFromCurrentLibrary()
{
FootprintLibs()->FootprintDelete( nickname, fpname );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
DisplayError( this, ioe.errorText );
return false;
......@@ -568,7 +568,7 @@ void PCB_EDIT_FRAME::ArchiveModulesOnBoard( bool aNewModulesOnly )
}
}
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
DisplayError( this, ioe.errorText );
}
......@@ -655,7 +655,7 @@ bool PCB_BASE_FRAME::Save_Module_In_Library( const wxString& aLibrary,
// own if the library or footprint is not writable.
FootprintLibs()->FootprintSave( aLibrary, aModule );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
DisplayError( this, ioe.errorText );
return false;
......
......@@ -220,7 +220,7 @@ MODULE* PCB_BASE_FRAME::LoadModuleFromLibrary( const wxString& aLibrary,
{
module = loadFootprint( fpid );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
wxLogDebug( wxT( "An error occurred attemping to load footprint '%s'.\n\nError: %s" ),
fpid.Format().c_str(), GetChars( ioe.errorText ) );
......@@ -252,7 +252,7 @@ MODULE* PCB_BASE_FRAME::LoadModuleFromLibrary( const wxString& aLibrary,
{
module = loadFootprint( fpid );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
wxLogDebug( wxT( "An error occurred attemping to load footprint '%s'.\n\nError: %s" ),
fpid.Format().c_str(), GetChars( ioe.errorText ) );
......@@ -304,7 +304,7 @@ MODULE* PCB_BASE_FRAME::LoadFootprint( const FPID& aFootprintId )
{
module = loadFootprint( aFootprintId );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
wxLogDebug( wxT( "An error occurred attemping to load footprint '%s'.\n\nError: %s" ),
aFootprintId.Format().c_str(), GetChars( ioe.errorText ) );
......@@ -321,31 +321,7 @@ MODULE* PCB_BASE_FRAME::loadFootprint( const FPID& aFootprintId )
wxCHECK_MSG( fptbl, NULL, wxT( "Cannot look up FPID in NULL FP_LIB_TABLE." ) );
wxString nickname = aFootprintId.GetLibNickname();
wxString fpname = aFootprintId.GetFootprintName();
if( nickname.size() )
{
return fptbl->FootprintLoad( nickname, fpname );
}
// user did not enter a nickname, just a footprint name, help him out a little:
else
{
std::vector<wxString> nicks = fptbl->GetLogicalLibs();
// Search each library going through libraries alphabetically.
for( unsigned i = 0; i<nicks.size(); ++i )
{
// FootprintLoad() returns NULL on not found, does not throw exception
// unless there's an IO_ERROR.
MODULE* ret = fptbl->FootprintLoad( nicks[i], fpname );
if( ret )
return ret;
}
return NULL;
}
return fptbl->FootprintLoadWithOptionalNickname( aFootprintId );
}
......@@ -557,7 +533,7 @@ void FOOTPRINT_EDIT_FRAME::OnSaveLibraryAs( wxCommandEvent& aEvent )
// m is deleted here by auto_ptr.
}
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
DisplayError( this, ioe.errorText );
return;
......
......@@ -279,7 +279,7 @@ wxString FOOTPRINT_EDIT_FRAME::getLibPath()
return row->GetFullURI( true );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
return wxEmptyString;
}
......@@ -639,7 +639,7 @@ void FOOTPRINT_EDIT_FRAME::updateTitle()
if( !writable )
title += _( " [Read Only]" );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
// user may be bewildered as to why after selecting a library it is not showing up
// in the title, we could show an error message, but that should have been done at time
......
......@@ -85,7 +85,7 @@ void PCB_EDIT_FRAME::ReadPcbNetlist( const wxString& aNetlistFileName,
netlistReader->LoadNetlist();
loadFootprints( netlist, aReporter );
}
catch( IO_ERROR& ioe )
catch( const IO_ERROR& ioe )
{
msg.Printf( _( "Error loading netlist.\n%s" ), ioe.errorText.GetData() );
wxMessageBox( msg, _( "Netlist Load Error" ), wxOK | wxICON_ERROR );
......
......@@ -208,13 +208,13 @@ MY_API( KIFACE* ) KIFACE_GETTER( int* aKIFACEversion, int aKiwayVersion, PGM_BA
return &kiface;
}
#if defined(BUILD_KIWAY_DLL)
PGM_BASE& Pgm()
{
wxASSERT( process ); // KIFACE_GETTER has already been called.
return *process;
}
#endif
/**
* Function set3DShapesPath
......@@ -484,6 +484,5 @@ void IFACE::OnKifaceEnd()
// This should only be called if python was setup correctly.
pcbnewFinishPythonScripting();
#endif
}
......@@ -29,7 +29,6 @@
*/
#include <fctsys.h>
//#include <pgm_base.h>
#include <kiface_i.h>
#include <project.h>
#include <class_drawpanel.h>
......@@ -239,7 +238,7 @@ bool PCB_EDIT_FRAME::LoadProjectSettings( const wxString& aProjectFileName )
fn.SetExt( ProjectFileExtension );
// was: wxGetApp().ReadProjectConfig( fn.GetFullPath(), GROUP, GetProjectFileParameters(), false );
Prj().ConfigLoad( Kiface().KifaceSearch(), fn.GetFullPath(), GROUP, GetProjectFileParameters(), false );
Prj().ConfigLoad( Kiface().KifaceSearch(), fn.GetFullPath(), GROUP_PCB, GetProjectFileParameters(), false );
// Dick 5-Feb-2012: I don't agree with this, the BOARD contents should dictate
// what is visible or not, even initially. And since PCB_EDIT_FRAME projects settings
......@@ -302,9 +301,7 @@ void PCB_EDIT_FRAME::SaveProjectSettings( bool aAskForSave )
fn = dlg.GetPath();
}
SEARCH_STACK& search = Kiface().KifaceSearch();
Prj().ConfigSave( search, fn.GetFullPath(), GROUP, GetProjectFileParameters() );
Prj().ConfigSave( Kiface().KifaceSearch(), fn.GetFullPath(), GROUP_PCB, GetProjectFileParameters() );
}
......@@ -315,7 +312,7 @@ PARAM_CFG_ARRAY PCB_EDIT_FRAME::GetProjectFileParameters()
pca.push_back( new PARAM_CFG_FILENAME( wxT( "PageLayoutDescrFile" ),
&BASE_SCREEN::m_PageLayoutDescrFileName ) );
pca.push_back( new PARAM_CFG_FILENAME( wxT( "LibDir" ), &g_UserLibDirBuffer, GROUPLIB ) );
pca.push_back( new PARAM_CFG_FILENAME( wxT( "LibDir" ), &g_UserLibDirBuffer, GROUP_PCB_LIBS ) );
pca.push_back( new PARAM_CFG_FILENAME( wxT( "LastNetListRead" ), &m_lastNetListRead ) );
......
/**
* @file pcbnew_config.h
* @brief Cconfiguration parameters for Pcbnew.
* @brief Configuration parameters for Pcbnew.
*/
#ifndef _PCBNEW_CONFIG_H_
......@@ -9,10 +9,6 @@
#include <config_params.h>
#include <colors_selection.h>
#define GROUP wxT( "/pcbnew" )
#define GROUPLIB wxT( "/pcbnew/libraries" )
#define GROUPCOMMON wxT( "/common" )
/* Useful macro : */
#define LOC_COLOR(layer) &g_ColorsSettings.m_LayersColors[layer]
#define ITEM_COLOR(item_visible) &g_ColorsSettings.m_ItemsColors[item_visible]
......
......@@ -162,7 +162,7 @@ bool PCB_EDIT_FRAME::ExportSpecctraFile( const wxString& aFullFilename )
// if an exception is thrown by FromBOARD or ExportPCB(), then
// ~SPECCTRA_DB() will close the file.
}
catch( IO_ERROR& ioe )
catch( const IO_ERROR& ioe )
{
ok = false;
......@@ -1322,7 +1322,7 @@ bool SPECCTRA_DB::GetBoardPolygonOutlines( BOARD* aBoard,
aHoles.CloseLastContour();
}
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
// Creates a valid polygon outline is not possible.
// So uses the board edge cuts bounding box to create a
......
......@@ -102,14 +102,15 @@ void PCB_EDIT_FRAME::ImportSpecctraSession( wxCommandEvent& event )
db.LoadSESSION( fullFileName );
db.FromSESSION( GetBoard() );
}
catch( IO_ERROR& ioe )
catch( const IO_ERROR& ioe )
{
ioe.errorText += '\n';
ioe.errorText += _("BOARD may be corrupted, do not save it.");
ioe.errorText += '\n';
ioe.errorText += _("Fix problem and try again.");
wxString msg = ioe.errorText;
msg += '\n';
msg += _("BOARD may be corrupted, do not save it.");
msg += '\n';
msg += _("Fix problem and try again.");
DisplayError( this, ioe.errorText );
DisplayError( this, msg );
return;
}
......
......@@ -63,7 +63,7 @@ int main( int argc, char** argv )
// db.LoadPCB( filename );
db.LoadSESSION( filename );
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
fprintf( stderr, "%s\n", TO_UTF8(ioe.errorText) );
failed = true;
......
......@@ -125,7 +125,10 @@ install_prerequisites()
fi
# ensure bzr name and email are set. No message since bzr prints an excellent diagnostic.
bzr whoami || exit 2
bzr whoami || {
echo "WARNING: You have not set bzr whoami, so I will set a dummy."
export BZR_EMAIL="Kicad Build <nobody@foo>"
}
}
......@@ -270,10 +273,12 @@ install_or_update()
echo " kicad-lib.bzr installed."
echo "step 9) as non-root, install user configuration files..."
echo "step 9) as non-root, install global fp-lib-table if none already installed..."
# install ~/fp-lib-table
make install_github_fp-lib-table
echo " kicad user-configuration files installed."
if [ ! -e ~/fp-lib-table ]; then
make install_github_fp-lib-table
echo " global fp-lib-table installed."
fi
echo "step 10) installing documentation..."
......
......@@ -83,7 +83,7 @@ int main( int argc, char** argv )
#endif
}
catch( IO_ERROR ioe )
catch( const IO_ERROR& ioe )
{
fprintf( stderr, "%s\n", TO_UTF8( ioe.errorText ) );
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment