Add text variable support to envVar processing.

This commit is contained in:
Jeff Young 2020-04-05 20:51:48 +01:00
parent a2102d87c5
commit cc9ac37a0e
24 changed files with 349 additions and 509 deletions

View File

@ -135,7 +135,7 @@ public:
~S3D_CACHE_ENTRY(); ~S3D_CACHE_ENTRY();
void SetSHA1( const unsigned char* aSHA1Sum ); void SetSHA1( const unsigned char* aSHA1Sum );
const wxString GetCacheBaseName( void ); const wxString GetCacheBaseName();
wxDateTime modTime; // file modification time wxDateTime modTime; // file modification time
unsigned char sha1sum[20]; unsigned char sha1sum[20];
@ -155,8 +155,7 @@ S3D_CACHE_ENTRY::S3D_CACHE_ENTRY()
S3D_CACHE_ENTRY::~S3D_CACHE_ENTRY() S3D_CACHE_ENTRY::~S3D_CACHE_ENTRY()
{ {
if( NULL != sceneData ) delete sceneData;
delete sceneData;
if( NULL != renderData ) if( NULL != renderData )
S3D::Destroy3DModel( &renderData ); S3D::Destroy3DModel( &renderData );
@ -174,11 +173,10 @@ void S3D_CACHE_ENTRY::SetSHA1( const unsigned char* aSHA1Sum )
} }
memcpy( sha1sum, aSHA1Sum, 20 ); memcpy( sha1sum, aSHA1Sum, 20 );
return;
} }
const wxString S3D_CACHE_ENTRY::GetCacheBaseName( void ) const wxString S3D_CACHE_ENTRY::GetCacheBaseName()
{ {
if( m_CacheBaseName.empty() ) if( m_CacheBaseName.empty() )
m_CacheBaseName = sha1ToWXString( sha1sum ); m_CacheBaseName = sha1ToWXString( sha1sum );
@ -189,11 +187,9 @@ const wxString S3D_CACHE_ENTRY::GetCacheBaseName( void )
S3D_CACHE::S3D_CACHE() S3D_CACHE::S3D_CACHE()
{ {
m_DirtyCache = false;
m_FNResolver = new FILENAME_RESOLVER; m_FNResolver = new FILENAME_RESOLVER;
m_project = nullptr;
m_Plugins = new S3D_PLUGIN_MANAGER; m_Plugins = new S3D_PLUGIN_MANAGER;
return;
} }
@ -201,13 +197,8 @@ S3D_CACHE::~S3D_CACHE()
{ {
FlushCache(); FlushCache();
if( m_FNResolver ) delete m_FNResolver;
delete m_FNResolver; delete m_Plugins;
if( m_Plugins )
delete m_Plugins;
return;
} }
@ -514,12 +505,7 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
if( !m_ConfigDir.empty() ) if( !m_ConfigDir.empty() )
return false; return false;
wxFileName cfgdir; wxFileName cfgdir( ExpandEnvVarSubstitutions( aConfigDir, m_project ), "" );
if( aConfigDir.StartsWith( "${" ) || aConfigDir.StartsWith( "$(" ) )
cfgdir.Assign( ExpandEnvVarSubstitutions( aConfigDir ), "" );
else
cfgdir.Assign( aConfigDir, "" );
cfgdir.Normalize(); cfgdir.Normalize();
@ -564,7 +550,7 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
#elif defined(__APPLE) #elif defined(__APPLE)
cacheDir = "${HOME}/Library/Caches/kicad/3d"; cacheDir = "${HOME}/Library/Caches/kicad/3d";
#else // assume Linux #else // assume Linux
cacheDir = ExpandEnvVarSubstitutions( "${XDG_CACHE_HOME}" ); cacheDir = ExpandEnvVarSubstitutions( "${XDG_CACHE_HOME}", nullptr );
if( cacheDir.empty() || cacheDir == "${XDG_CACHE_HOME}" ) if( cacheDir.empty() || cacheDir == "${XDG_CACHE_HOME}" )
cacheDir = "${HOME}/.cache"; cacheDir = "${HOME}/.cache";
@ -572,7 +558,7 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
cacheDir.append( "/kicad/3d" ); cacheDir.append( "/kicad/3d" );
#endif #endif
cacheDir = ExpandEnvVarSubstitutions( cacheDir ); cacheDir = ExpandEnvVarSubstitutions( cacheDir, m_project );
cfgdir.Assign( cacheDir, "" ); cfgdir.Assign( cacheDir, "" );
if( !cfgdir.DirExists() ) if( !cfgdir.DirExists() )
@ -593,66 +579,13 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
} }
wxString S3D_CACHE::Get3DConfigDir( bool createDefault ) bool S3D_CACHE::SetProject( PROJECT* aProject )
{ {
if( !m_ConfigDir.empty() || !createDefault ) m_project = aProject;
return m_ConfigDir;
// note: duplicated from common/common.cpp GetKicadConfigPath() to avoid
// code coupling; ideally the instantiating code should call
// Set3DConfigDir() to set the directory rather than relying on this
// directory remaining the same in future KiCad releases.
wxFileName cfgpath;
// From the wxWidgets wxStandardPaths::GetUserConfigDir() help:
// Unix: ~ (the home directory)
// Windows: "C:\Documents and Settings\username\Application Data"
// Mac: ~/Library/Preferences
cfgpath.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
#if !defined( __WINDOWS__ ) && !defined( __WXMAC__ )
wxString envstr = ExpandEnvVarSubstitutions( "${XDG_CONFIG_HOME}" );
if( envstr.IsEmpty() || envstr == "${XDG_CONFIG_HOME}" )
{
// XDG_CONFIG_HOME is not set, so use the fallback
cfgpath.AppendDir( wxT( ".config" ) );
}
else
{
// Override the assignment above with XDG_CONFIG_HOME
cfgpath.AssignDir( envstr );
}
#endif
cfgpath.AppendDir( wxT( "kicad" ) );
cfgpath.AppendDir( wxT( "3d" ) );
if( !cfgpath.DirExists() )
{
cfgpath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
}
if( !cfgpath.DirExists() )
{
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * failed to create 3D configuration directory '%s'",
__FILE__, __FUNCTION__, __LINE__, cfgpath.GetPath() );
return wxT( "" );
}
if( Set3DConfigDir( cfgpath.GetPath() ) )
return m_ConfigDir;
return wxEmptyString;
}
bool S3D_CACHE::SetProjectDir( const wxString& aProjDir )
{
bool hasChanged = false; bool hasChanged = false;
if( m_FNResolver->SetProjectDir( aProjDir, &hasChanged ) && hasChanged ) if( m_FNResolver->SetProject( aProject, &hasChanged ) && hasChanged )
{ {
m_CacheMap.clear(); m_CacheMap.clear();
@ -677,23 +610,16 @@ bool S3D_CACHE::SetProjectDir( const wxString& aProjDir )
void S3D_CACHE::SetProgramBase( PGM_BASE* aBase ) void S3D_CACHE::SetProgramBase( PGM_BASE* aBase )
{ {
m_FNResolver->SetProgramBase( aBase ); m_FNResolver->SetProgramBase( aBase );
return;
} }
wxString S3D_CACHE::GetProjectDir( void ) FILENAME_RESOLVER* S3D_CACHE::GetResolver()
{
return m_FNResolver->GetProjectDir();
}
FILENAME_RESOLVER* S3D_CACHE::GetResolver( void )
{ {
return m_FNResolver; return m_FNResolver;
} }
std::list< wxString > const* S3D_CACHE::GetFileFilters( void ) const std::list< wxString > const* S3D_CACHE::GetFileFilters() const
{ {
return m_Plugins->GetFileFilters(); return m_Plugins->GetFileFilters();
} }
@ -715,17 +641,13 @@ void S3D_CACHE::FlushCache( bool closePlugins )
if( closePlugins ) if( closePlugins )
ClosePlugins(); ClosePlugins();
return;
} }
void S3D_CACHE::ClosePlugins( void ) void S3D_CACHE::ClosePlugins()
{ {
if( NULL != m_Plugins ) if( m_Plugins )
m_Plugins->ClosePlugins(); m_Plugins->ClosePlugins();
return;
} }
@ -756,31 +678,6 @@ S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName )
} }
wxString S3D_CACHE::GetModelHash( const wxString& aModelFileName )
{
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFileName );
if( full3Dpath.empty() || !wxFileName::FileExists( full3Dpath ) )
return wxEmptyString;
// check cache if file is already loaded
std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString >::iterator mi;
mi = m_CacheMap.find( full3Dpath );
if( mi != m_CacheMap.end() )
return mi->second->GetCacheBaseName();
// a cache item does not exist; search the Filename->Cachename map
S3D_CACHE_ENTRY* cp = NULL;
checkCache( full3Dpath, &cp );
if( NULL != cp )
return cp->GetCacheBaseName();
return wxEmptyString;
}
S3D_CACHE* PROJECT::Get3DCacheManager( bool aUpdateProjDir ) S3D_CACHE* PROJECT::Get3DCacheManager( bool aUpdateProjDir )
{ {
std::lock_guard<std::mutex> lock( mutex3D_cacheManager ); std::lock_guard<std::mutex> lock( mutex3D_cacheManager );
@ -805,7 +702,7 @@ S3D_CACHE* PROJECT::Get3DCacheManager( bool aUpdateProjDir )
} }
if( aUpdateProjDir ) if( aUpdateProjDir )
cache->SetProjectDir( GetProjectPath() ); cache->SetProject( this );
return cache; return cache;
} }

View File

@ -60,23 +60,13 @@ private:
/// mapping of file names to cache names and data /// mapping of file names to cache names and data
std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString > m_CacheMap; std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString > m_CacheMap;
/// object to resolve file names FILENAME_RESOLVER* m_FNResolver;
FILENAME_RESOLVER* m_FNResolver;
/// plugin manager
S3D_PLUGIN_MANAGER* m_Plugins; S3D_PLUGIN_MANAGER* m_Plugins;
/// set true if the cache needs to be updated PROJECT* m_project;
bool m_DirtyCache; wxString m_CacheDir;
wxString m_ConfigDir; /// base configuration path for 3D items
/// 3D cache directory
wxString m_CacheDir;
/// base configuration path for 3D items
wxString m_ConfigDir;
/// current KiCad project dir
wxString m_ProjDir;
/** Find or create cache entry for file name /** Find or create cache entry for file name
* *
@ -133,22 +123,12 @@ public:
*/ */
bool Set3DConfigDir( const wxString& aConfigDir ); bool Set3DConfigDir( const wxString& aConfigDir );
/**
* Function Get3DConfigDir
* returns the current 3D configuration directory on
* success, otherwise it returns wxEmptyString. If the
* directory was not previously set via Set3DConfigDir()
* then a default is used which is based on kicad's
* configuration directory code as of September 2015.
*/
wxString Get3DConfigDir( bool createDefault = false );
/** /**
* Function SetProjectDir * Function SetProjectDir
* sets the current project's working directory; this * sets the current project's working directory; this
* affects the model search path * affects the model search path
*/ */
bool SetProjectDir( const wxString& aProjDir ); bool SetProject( PROJECT* aProject );
/** /**
* Function SetProgramBase * Function SetProgramBase
@ -158,12 +138,6 @@ public:
*/ */
void SetProgramBase( PGM_BASE* aBase ); void SetProgramBase( PGM_BASE* aBase );
/**
* Function GetProjectDir
* returns the current project's working directory
*/
wxString GetProjectDir( void );
/** /**
* Function Load * Function Load
* attempts to load the scene data for a model; it will consult the * attempts to load the scene data for a model; it will consult the
@ -177,7 +151,7 @@ public:
*/ */
SCENEGRAPH* Load( const wxString& aModelFile ); SCENEGRAPH* Load( const wxString& aModelFile );
FILENAME_RESOLVER* GetResolver( void ); FILENAME_RESOLVER* GetResolver();
/** /**
* Function GetFileFilters * Function GetFileFilters
@ -186,7 +160,7 @@ public:
* *
* @return a pointer to the filter list * @return a pointer to the filter list
*/ */
std::list< wxString > const* GetFileFilters( void ) const; std::list< wxString > const* GetFileFilters() const;
/** /**
* Function FlushCache * Function FlushCache
@ -198,7 +172,7 @@ public:
* Function ClosePlugins * Function ClosePlugins
* unloads plugins to free memory * unloads plugins to free memory
*/ */
void ClosePlugins( void ); void ClosePlugins();
/** /**
* Function GetModel * Function GetModel
@ -209,8 +183,6 @@ public:
* @return is a pointer to the render data or NULL if not available * @return is a pointer to the render data or NULL if not available
*/ */
S3DMODEL* GetModel( const wxString& aModelFileName ); S3DMODEL* GetModel( const wxString& aModelFileName );
wxString GetModelHash( const wxString& aModelFileName );
}; };
#endif // CACHE_3D_H #endif // CACHE_3D_H

View File

@ -340,12 +340,7 @@ void S3D_PLUGIN_MANAGER::checkPluginName( const wxString& aPath,
if( aPath.empty() || !wxFileName::FileExists( aPath ) ) if( aPath.empty() || !wxFileName::FileExists( aPath ) )
return; return;
wxFileName path; wxFileName path( ExpandEnvVarSubstitutions( aPath, nullptr ) );
if( aPath.StartsWith( "${" ) || aPath.StartsWith( "$(" ) )
path.Assign( ExpandEnvVarSubstitutions( aPath ) );
else
path.Assign( aPath );
path.Normalize(); path.Normalize();
@ -374,7 +369,7 @@ void S3D_PLUGIN_MANAGER::checkPluginName( const wxString& aPath,
void S3D_PLUGIN_MANAGER::checkPluginPath( const wxString& aPath, void S3D_PLUGIN_MANAGER::checkPluginPath( const wxString& aPath,
std::list< wxString >& aSearchList ) std::list< wxString >& aSearchList )
{ {
// check the existence of a path and add it to the path search list // check the existence of a path and add it to the path search list
if( aPath.empty() ) if( aPath.empty() )
@ -388,7 +383,7 @@ void S3D_PLUGIN_MANAGER::checkPluginPath( const wxString& aPath,
wxFileName path; wxFileName path;
if( aPath.StartsWith( "${" ) || aPath.StartsWith( "$(" ) ) if( aPath.StartsWith( "${" ) || aPath.StartsWith( "$(" ) )
path.Assign( ExpandEnvVarSubstitutions( aPath ), "" ); path.Assign( ExpandEnvVarSubstitutions( aPath, nullptr ), "" );
else else
path.Assign( aPath, "" ); path.Assign( aPath, "" );

View File

@ -373,7 +373,7 @@ enum Bracket
wxString ExpandTextVars( const wxString& aSource, wxString ExpandTextVars( const wxString& aSource,
const std::function<bool( wxString* )>& aLocalResolver, const std::function<bool( wxString* )>* aLocalResolver,
const PROJECT* aProject ) const PROJECT* aProject )
{ {
wxString newbuf; wxString newbuf;
@ -396,7 +396,11 @@ wxString ExpandTextVars( const wxString& aSource,
if( token.IsEmpty() ) if( token.IsEmpty() )
continue; continue;
if( aLocalResolver( &token ) || ( aProject && aProject->TextVarResolver( &token ) ) ) if( aLocalResolver && (*aLocalResolver)( &token ) )
{
newbuf.append( token );
}
else if( aProject && aProject->TextVarResolver( &token ) )
{ {
newbuf.append( token ); newbuf.append( token );
} }
@ -419,7 +423,7 @@ wxString ExpandTextVars( const wxString& aSource,
// //
// Stolen from wxExpandEnvVars and then heavily optimized // Stolen from wxExpandEnvVars and then heavily optimized
// //
wxString KIwxExpandEnvVars(const wxString& str) wxString KIwxExpandEnvVars( const wxString& str, const PROJECT* aProject )
{ {
size_t strlen = str.length(); size_t strlen = str.length();
@ -477,9 +481,14 @@ wxString KIwxExpandEnvVars(const wxString& str)
// NB: use wxGetEnv instead of wxGetenv as otherwise variables // NB: use wxGetEnv instead of wxGetenv as otherwise variables
// set through wxSetEnv may not be read correctly! // set through wxSetEnv may not be read correctly!
bool expanded = false; bool expanded = false;
wxString tmp; wxString tmp = strVarName;
if( wxGetEnv( strVarName, &tmp ) ) if( aProject && aProject->TextVarResolver( &tmp ) )
{
strResult += tmp;
expanded = true;
}
else if( wxGetEnv( strVarName, &tmp ) )
{ {
strResult += tmp; strResult += tmp;
expanded = true; expanded = true;
@ -548,7 +557,7 @@ wxString KIwxExpandEnvVars(const wxString& str)
} }
const wxString ExpandEnvVarSubstitutions( const wxString& aString ) const wxString ExpandEnvVarSubstitutions( const wxString& aString, PROJECT* aProject )
{ {
// wxGetenv( wchar_t* ) is not re-entrant on linux. // wxGetenv( wchar_t* ) is not re-entrant on linux.
// Put a lock on multithreaded use of wxGetenv( wchar_t* ), called from wxEpandEnvVars(), // Put a lock on multithreaded use of wxGetenv( wchar_t* ), called from wxEpandEnvVars(),
@ -557,21 +566,22 @@ const wxString ExpandEnvVarSubstitutions( const wxString& aString )
std::lock_guard<std::mutex> lock( getenv_mutex ); std::lock_guard<std::mutex> lock( getenv_mutex );
// We reserve the right to do this another way, by providing our own member function. // We reserve the right to do this another way, by providing our own member function.
return KIwxExpandEnvVars( aString ); return KIwxExpandEnvVars( aString, aProject );
} }
const wxString ResolveUriByEnvVars( const wxString& aUri ) const wxString ResolveUriByEnvVars( const wxString& aUri, PROJECT* aProject )
{ {
wxString uri = ExpandTextVars( aUri, nullptr, aProject );
// URL-like URI: return as is. // URL-like URI: return as is.
wxURL url( aUri ); wxURL url( uri );
if( url.GetError() == wxURL_NOERR ) if( url.GetError() == wxURL_NOERR )
return aUri; return uri;
// Otherwise, the path points to a local file. Resolve environment // Otherwise, the path points to a local file. Resolve environment variables if any.
// variables if any. return ExpandEnvVarSubstitutions( aUri, aProject );
return ExpandEnvVarSubstitutions( aUri );
} }

View File

@ -77,15 +77,18 @@ static const wxFileTypeInfo EDAfallbacks[] =
}; };
bool GetAssociatedDocument( wxWindow* aParent, bool GetAssociatedDocument( wxWindow* aParent, const wxString& aDocName, PROJECT* aProject )
const wxString& aDocName,
const wxPathList* aPaths)
{ {
wxString docname, fullfilename; SEARCH_STACK* aPaths = nullptr;
wxString msg; wxString docname;
wxString command; wxString fullfilename;
bool success = false; wxString msg;
wxString command;
bool success = false;
#if defined(EESCHEMA)
SEARCH_STACK* aPaths = aProject ? aProject->SchSearchS() : nullptr;
#endif
// Is an internet url // Is an internet url
static const wxChar* url_header[] = { static const wxChar* url_header[] = {
@ -97,11 +100,11 @@ bool GetAssociatedDocument( wxWindow* aParent,
}; };
// Replace before resolving as we might have a URL in a variable // Replace before resolving as we might have a URL in a variable
docname = ResolveUriByEnvVars( aDocName ); docname = ResolveUriByEnvVars( aDocName, aProject );
for( unsigned ii = 0; ii < arrayDim(url_header); ii++ ) for( const wxString& proc : url_header)
{ {
if( docname.First( url_header[ii] ) == 0 ) // looks like an internet url if( docname.First( proc ) == 0 ) // looks like an internet url
{ {
wxURI uri( docname ); wxURI uri( docname );
wxLaunchDefaultBrowser( uri.BuildURI() ); wxLaunchDefaultBrowser( uri.BuildURI() );
@ -117,7 +120,7 @@ bool GetAssociatedDocument( wxWindow* aParent,
/* Compute the full file name */ /* Compute the full file name */
if( wxIsAbsolutePath( docname ) || aPaths == NULL) if( wxIsAbsolutePath( docname ) || aPaths == NULL )
fullfilename = docname; fullfilename = docname;
/* If the file exists, this is a trivial case: return the filename /* If the file exists, this is a trivial case: return the filename
* "as this". the name can be an absolute path, or a relative path * "as this". the name can be an absolute path, or a relative path
@ -126,9 +129,7 @@ bool GetAssociatedDocument( wxWindow* aParent,
else if( wxFileName::FileExists( docname ) ) else if( wxFileName::FileExists( docname ) )
fullfilename = docname; fullfilename = docname;
else else
{
fullfilename = aPaths->FindValidPath( docname ); fullfilename = aPaths->FindValidPath( docname );
}
wxString mask( wxT( "*" ) ), extension; wxString mask( wxT( "*" ) ), extension;

View File

@ -50,10 +50,11 @@ static std::mutex mutex_resolver;
static bool getHollerith( const std::string& aString, size_t& aIndex, wxString& aResult ); static bool getHollerith( const std::string& aString, size_t& aIndex, wxString& aResult );
FILENAME_RESOLVER::FILENAME_RESOLVER() FILENAME_RESOLVER::FILENAME_RESOLVER() :
m_pgm( nullptr ),
m_project( nullptr )
{ {
m_errflags = 0; m_errflags = 0;
m_pgm = NULL;
} }
@ -62,12 +63,7 @@ bool FILENAME_RESOLVER::Set3DConfigDir( const wxString& aConfigDir )
if( aConfigDir.empty() ) if( aConfigDir.empty() )
return false; return false;
wxFileName cfgdir; wxFileName cfgdir( ExpandEnvVarSubstitutions( aConfigDir, m_project ), "" );
if( aConfigDir.StartsWith( "${" ) || aConfigDir.StartsWith( "$(" ) )
cfgdir.Assign( ExpandEnvVarSubstitutions( aConfigDir ), "" );
else
cfgdir.Assign( aConfigDir, "" );
cfgdir.Normalize(); cfgdir.Normalize();
@ -81,17 +77,14 @@ bool FILENAME_RESOLVER::Set3DConfigDir( const wxString& aConfigDir )
} }
bool FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgChanged ) bool FILENAME_RESOLVER::SetProject( PROJECT* aProject, bool* flgChanged )
{ {
if( aProjDir.empty() ) m_project = aProject;
if( !aProject )
return false; return false;
wxFileName projdir; wxFileName projdir( ExpandEnvVarSubstitutions( aProject->GetProjectPath(), aProject ), "" );
if( aProjDir.StartsWith( "${" ) || aProjDir.StartsWith( "$(" ) )
projdir.Assign( ExpandEnvVarSubstitutions( aProjDir ), "" );
else
projdir.Assign( aProjDir, "" );
projdir.Normalize(); projdir.Normalize();
@ -113,7 +106,6 @@ bool FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgChange
if( flgChanged ) if( flgChanged )
*flgChanged = true; *flgChanged = true;
} }
else else
{ {
@ -123,7 +115,6 @@ bool FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgChange
if( flgChanged ) if( flgChanged )
*flgChanged = true; *flgChanged = true;
} }
else else
{ {
@ -132,13 +123,13 @@ bool FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgChange
} }
#ifdef DEBUG #ifdef DEBUG
do { {
std::ostringstream ostr; std::ostringstream ostr;
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
ostr << " * [INFO] changed project dir to "; ostr << " * [INFO] changed project dir to ";
ostr << m_Paths.front().m_pathexp.ToUTF8(); ostr << m_Paths.front().m_pathexp.ToUTF8();
wxLogTrace( MASK_3D_RESOLVER, "%s\n", ostr.str().c_str() ); wxLogTrace( MASK_3D_RESOLVER, "%s\n", ostr.str().c_str() );
} while( 0 ); }
#endif #endif
return true; return true;
@ -188,7 +179,7 @@ bool FILENAME_RESOLVER::createPathList()
{ {
for( const wxString& curr_path : epaths ) for( const wxString& curr_path : epaths )
{ {
wxString pathVal = ExpandEnvVarSubstitutions( curr_path ); wxString pathVal = ExpandEnvVarSubstitutions( curr_path, m_project );
if( pathVal.empty() ) if( pathVal.empty() )
{ {
@ -272,8 +263,7 @@ wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
// wxFileName::Normalize() routine to perform expansion then // wxFileName::Normalize() routine to perform expansion then
// we will have a race condition since wxWidgets does not assure // we will have a race condition since wxWidgets does not assure
// a threadsafe wrapper for getenv(). // a threadsafe wrapper for getenv().
if( tname.StartsWith( "${" ) || tname.StartsWith( "$(" ) ) tname = ExpandEnvVarSubstitutions( tname, m_project );
tname = ExpandEnvVarSubstitutions( tname );
wxFileName tmpFN( tname ); wxFileName tmpFN( tname );
@ -341,8 +331,7 @@ wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
tmpFN.Assign( sPL->m_pathexp, "" ); tmpFN.Assign( sPL->m_pathexp, "" );
wxString fullPath = tmpFN.GetPathWithSep() + tname; wxString fullPath = tmpFN.GetPathWithSep() + tname;
if( fullPath.StartsWith( "${" ) || fullPath.StartsWith( "$(" ) ) fullPath = ExpandEnvVarSubstitutions( fullPath, m_project );
fullPath = ExpandEnvVarSubstitutions( fullPath );
if( wxFileName::FileExists( fullPath ) ) if( wxFileName::FileExists( fullPath ) )
{ {
@ -361,7 +350,7 @@ wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
wxString fullPath( "${KISYS3DMOD}" ); wxString fullPath( "${KISYS3DMOD}" );
fullPath.Append( fpath.GetPathSeparator() ); fullPath.Append( fpath.GetPathSeparator() );
fullPath.Append( tname ); fullPath.Append( tname );
fullPath = ExpandEnvVarSubstitutions( fullPath ); fullPath = ExpandEnvVarSubstitutions( fullPath, m_project );
fpath.Assign( fullPath ); fpath.Assign( fullPath );
if( fpath.Normalize() && fpath.FileExists() ) if( fpath.Normalize() && fpath.FileExists() )
@ -404,8 +393,7 @@ wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
wxFileName fpath( wxFileName::DirName( sPL->m_pathexp ) ); wxFileName fpath( wxFileName::DirName( sPL->m_pathexp ) );
wxString fullPath = fpath.GetPathWithSep() + relpath; wxString fullPath = fpath.GetPathWithSep() + relpath;
if( fullPath.StartsWith( "${") || fullPath.StartsWith( "$(" ) ) fullPath = ExpandEnvVarSubstitutions( fullPath, m_project );
fullPath = ExpandEnvVarSubstitutions( fullPath );
if( wxFileName::FileExists( fullPath ) ) if( wxFileName::FileExists( fullPath ) )
{ {
@ -452,12 +440,7 @@ bool FILENAME_RESOLVER::addPath( const SEARCH_PATH& aPath )
tpath.m_pathvar.erase( tpath.m_pathvar.length() - 1 ); tpath.m_pathvar.erase( tpath.m_pathvar.length() - 1 );
#endif #endif
wxFileName path; wxFileName path( ExpandEnvVarSubstitutions( tpath.m_pathvar, m_project ), "" );
if( tpath.m_pathvar.StartsWith( "${" ) || tpath.m_pathvar.StartsWith( "$(" ) )
path.Assign( ExpandEnvVarSubstitutions( tpath.m_pathvar ), "" );
else
path.Assign( tpath.m_pathvar, "" );
path.Normalize(); path.Normalize();
@ -728,12 +711,7 @@ void FILENAME_RESOLVER::checkEnvVarPath( const wxString& aPath )
SEARCH_PATH lpath; SEARCH_PATH lpath;
lpath.m_alias = envar; lpath.m_alias = envar;
lpath.m_pathvar = lpath.m_alias; lpath.m_pathvar = lpath.m_alias;
wxFileName tmpFN; wxFileName tmpFN( ExpandEnvVarSubstitutions( lpath.m_alias, m_project ), "" );
if( lpath.m_alias.StartsWith( "${" ) || lpath.m_alias.StartsWith( "$(" ) )
tmpFN.Assign( ExpandEnvVarSubstitutions( lpath.m_alias ), "" );
else
tmpFN.Assign( lpath.m_alias, "" );
wxUniChar psep = tmpFN.GetPathSeparator(); wxUniChar psep = tmpFN.GetPathSeparator();
tmpFN.Normalize(); tmpFN.Normalize();
@ -780,7 +758,7 @@ wxString FILENAME_RESOLVER::ShortenPath( const wxString& aFullPathName )
// in the case of aliases, ensure that we use the most recent definition // in the case of aliases, ensure that we use the most recent definition
if( sL->m_alias.StartsWith( "${" ) || sL->m_alias.StartsWith( "$(" ) ) if( sL->m_alias.StartsWith( "${" ) || sL->m_alias.StartsWith( "$(" ) )
{ {
wxString tpath = ExpandEnvVarSubstitutions( sL->m_alias ); wxString tpath = ExpandEnvVarSubstitutions( sL->m_alias, m_project );
if( tpath.empty() ) if( tpath.empty() )
{ {

View File

@ -74,7 +74,7 @@ const wxString LIB_TABLE_ROW::GetFullURI( bool aSubstituted ) const
return uri_expanded; return uri_expanded;
#else // late expansion #else // late expansion
return LIB_TABLE::ExpandSubstitutions( uri_user ); return ExpandEnvVarSubstitutions( uri_user, nullptr );
#endif #endif
} }
@ -449,9 +449,3 @@ UTF8 LIB_TABLE::FormatOptions( const PROPERTIES* aProperties )
return ret; return ret;
} }
const wxString LIB_TABLE::ExpandSubstitutions( const wxString& aString )
{
return ExpandEnvVarSubstitutions( aString );
}

View File

@ -194,7 +194,7 @@ const wxString WS_DATA_MODEL::MakeShortFileName( const wxString& aFullFileName,
const wxString WS_DATA_MODEL::MakeFullFileName( const wxString& aShortFileName, const wxString WS_DATA_MODEL::MakeFullFileName( const wxString& aShortFileName,
const wxString& aProjectPath ) const wxString& aProjectPath )
{ {
wxString fullFileName = ExpandEnvVarSubstitutions( aShortFileName ); wxString fullFileName = ExpandEnvVarSubstitutions( aShortFileName, nullptr );
if( fullFileName.IsEmpty() ) if( fullFileName.IsEmpty() )
return fullFileName; return fullFileName;

View File

@ -89,93 +89,94 @@ const COLOR4D& WS_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer
// after replacing format symbols by the corresponding value // after replacing format symbols by the corresponding value
wxString WS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase ) wxString WS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase )
{ {
auto wsResolver = [ this ]( wxString* token ) -> bool std::function<bool( wxString* )> wsResolver =
{ [ this ]( wxString* token ) -> bool
if( token->IsSameAs( wxT( "KICAD_VERSION" ) ) ) {
{ if( token->IsSameAs( wxT( "KICAD_VERSION" ) ))
*token = wxString::Format( wxT( "%s%s %s" ), {
productName, *token = wxString::Format( wxT( "%s%s %s" ),
Pgm().App().GetAppName(), productName,
GetBuildVersion() ); Pgm().App().GetAppName(),
return true; GetBuildVersion());
} return true;
else if( token->IsSameAs( wxT( "#" ) ) ) }
{ else if( token->IsSameAs( wxT( "#" ) ))
*token = wxString::Format( wxT( "%d" ), m_sheetNumber ); {
return true; *token = wxString::Format( wxT( "%d" ), m_sheetNumber );
} return true;
else if( token->IsSameAs( wxT( "##" ) ) ) }
{ else if( token->IsSameAs( wxT( "##" ) ))
*token = wxString::Format( wxT( "%d" ), m_sheetCount ); {
return true; *token = wxString::Format( wxT( "%d" ), m_sheetCount );
} return true;
else if( token->IsSameAs( wxT( "SHEETNAME" ) ) ) }
{ else if( token->IsSameAs( wxT( "SHEETNAME" ) ))
*token = m_sheetFullName; {
return true; *token = m_sheetFullName;
} return true;
else if( token->IsSameAs( wxT( "FILENAME" ) ) ) }
{ else if( token->IsSameAs( wxT( "FILENAME" ) ))
wxFileName fn( m_fileName ); {
*token = fn.GetFullName(); wxFileName fn( m_fileName );
return true; *token = fn.GetFullName();
} return true;
else if( token->IsSameAs( wxT( "PAPER" ) ) ) }
{ else if( token->IsSameAs( wxT( "PAPER" ) ))
*token = m_paperFormat ? *m_paperFormat : wxString(""); {
return true; *token = m_paperFormat ? *m_paperFormat : wxString( "" );
} return true;
else if( token->IsSameAs( wxT( "LAYER" ) ) ) }
{ else if( token->IsSameAs( wxT( "LAYER" ) ))
*token = m_sheetLayer ? *m_sheetLayer : wxString(""); {
return true; *token = m_sheetLayer ? *m_sheetLayer : wxString( "" );
} return true;
else if( token->IsSameAs( wxT( "ISSUE_DATE" ) ) ) }
{ else if( token->IsSameAs( wxT( "ISSUE_DATE" ) ))
*token = m_titleBlock ? m_titleBlock->GetDate() : wxString(""); {
return true; *token = m_titleBlock ? m_titleBlock->GetDate() : wxString( "" );
} return true;
else if( token->IsSameAs( wxT( "REVISION" ) ) ) }
{ else if( token->IsSameAs( wxT( "REVISION" ) ))
*token = m_titleBlock ? m_titleBlock->GetRevision() : wxString(""); {
return true; *token = m_titleBlock ? m_titleBlock->GetRevision() : wxString( "" );
} return true;
else if( token->IsSameAs( wxT( "TITLE" ) ) ) }
{ else if( token->IsSameAs( wxT( "TITLE" ) ))
*token = m_titleBlock ? m_titleBlock->GetTitle() : wxString(""); {
return true; *token = m_titleBlock ? m_titleBlock->GetTitle() : wxString( "" );
} return true;
else if( token->IsSameAs( wxT( "COMPANY" ) ) ) }
{ else if( token->IsSameAs( wxT( "COMPANY" ) ))
*token = m_titleBlock ? m_titleBlock->GetCompany() : wxString(""); {
return true; *token = m_titleBlock ? m_titleBlock->GetCompany() : wxString( "" );
} return true;
else if( token->Left( token->Len()-1 ).IsSameAs( wxT( "COMMENT" ) ) ) }
{ else if( token->Left( token->Len() - 1 ).IsSameAs( wxT( "COMMENT" ) ))
wxChar c = token->Last(); {
wxChar c = token->Last();
switch( c ) switch( c )
{ {
case '0': case '0':
case '1': case '1':
case '2': case '2':
case '3': case '3':
case '4': case '4':
case '5': case '5':
case '6': case '6':
case '7': case '7':
case '8': case '8':
case '9': case '9':
*token = m_titleBlock ? m_titleBlock->GetComment( c - '0' ) *token = m_titleBlock ? m_titleBlock->GetComment( c - '0' )
: wxString(""); : wxString( "" );
return true; return true;
} }
} }
return false; return false;
}; };
return ExpandTextVars( aTextbase, wsResolver, m_project ); return ExpandTextVars( aTextbase, &wsResolver, m_project );
} }

View File

@ -171,7 +171,7 @@ int COMMON_CONTROL::ShowHelp( const TOOL_EVENT& aEvent )
} }
} }
GetAssociatedDocument( m_frame, helpFile ); GetAssociatedDocument( m_frame, helpFile, &m_frame->Kiway().Prj() );
return 0; return 0;
} }

View File

@ -286,7 +286,7 @@ protected:
wxString filename = GetValue(); wxString filename = GetValue();
if( !filename.IsEmpty() && filename != wxT( "~" ) ) if( !filename.IsEmpty() && filename != wxT( "~" ) )
GetAssociatedDocument( m_dlg, GetValue() ); GetAssociatedDocument( m_dlg, GetValue(), &m_dlg->Kiway().Prj() );
} }
DIALOG_SHIM* m_dlg; DIALOG_SHIM* m_dlg;
@ -336,7 +336,7 @@ protected:
if( path.IsEmpty() ) if( path.IsEmpty() )
path = *m_currentDir; path = *m_currentDir;
else else
path = ExpandEnvVarSubstitutions( path ); path = ExpandEnvVarSubstitutions( path, &m_dlg->Kiway().Prj() );
if( m_ext ) if( m_ext )
{ {

View File

@ -97,7 +97,7 @@ protected:
else if (event.GetId() == MYID_SHOW_DATASHEET ) else if (event.GetId() == MYID_SHOW_DATASHEET )
{ {
wxString datasheet_uri = m_grid->GetCellValue( m_grid->GetGridCursorRow(), DATASHEET ); wxString datasheet_uri = m_grid->GetCellValue( m_grid->GetGridCursorRow(), DATASHEET );
GetAssociatedDocument( m_dlg, datasheet_uri ); GetAssociatedDocument( m_dlg, datasheet_uri, &m_dlg->Kiway().Prj() );
} }
else else
{ {

View File

@ -691,7 +691,7 @@ void FIELDS_GRID_TRICKS::doPopupSelection( wxCommandEvent& event )
else if (event.GetId() == MYID_SHOW_DATASHEET ) else if (event.GetId() == MYID_SHOW_DATASHEET )
{ {
wxString datasheet_uri = m_grid->GetCellValue( DATASHEET, FDC_VALUE ); wxString datasheet_uri = m_grid->GetCellValue( DATASHEET, FDC_VALUE );
GetAssociatedDocument( m_dlg, datasheet_uri ); GetAssociatedDocument( m_dlg, datasheet_uri, &m_dlg->Kiway().Prj() );
} }
else else
{ {

View File

@ -74,100 +74,102 @@ EDA_ITEM* SCH_FIELD::Clone() const
wxString SCH_FIELD::GetShownText() const wxString SCH_FIELD::GetShownText() const
{ {
auto symbolResolver = [ this ]( wxString* token ) -> bool std::function<bool( wxString* )> symbolResolver =
{ [this]( wxString* token ) -> bool
SCH_COMPONENT* component = static_cast<SCH_COMPONENT*>( m_Parent ); {
std::vector<SCH_FIELD>& fields = component->GetFields(); SCH_COMPONENT* component = static_cast<SCH_COMPONENT*>( m_Parent );
std::vector<SCH_FIELD>& fields = component->GetFields();
for( int i = 0; i < MANDATORY_FIELDS; ++i ) for( int i = 0; i < MANDATORY_FIELDS; ++i )
{ {
if( token->IsSameAs( fields[i].GetCanonicalName().Upper() ) ) if( token->IsSameAs( fields[ i ].GetCanonicalName().Upper()))
{ {
// silently drop recursive references // silently drop recursive references
if( &fields[i] == this ) if( &fields[ i ] == this )
*token = wxEmptyString; *token = wxEmptyString;
else else
*token = fields[i].GetShownText(); *token = fields[ i ].GetShownText();
return true; return true;
} }
} }
for( size_t i = MANDATORY_FIELDS; i < fields.size(); ++i ) for( size_t i = MANDATORY_FIELDS; i < fields.size(); ++i )
{ {
if( token->IsSameAs( fields[i].GetName() ) if( token->IsSameAs( fields[ i ].GetName())
|| token->IsSameAs( fields[i].GetName().Upper() ) ) || token->IsSameAs( fields[ i ].GetName().Upper()))
{ {
// silently drop recursive references // silently drop recursive references
if( &fields[i] == this ) if( &fields[ i ] == this )
*token = wxEmptyString; *token = wxEmptyString;
else else
*token = fields[i].GetShownText(); *token = fields[ i ].GetShownText();
return true; return true;
} }
} }
if( token->IsSameAs( wxT( "FOOTPRINT_LIBRARY" ) ) ) if( token->IsSameAs( wxT( "FOOTPRINT_LIBRARY" ) ))
{ {
SCH_FIELD& f = component->GetFields()[ FOOTPRINT ]; SCH_FIELD& f = component->GetFields()[ FOOTPRINT ];
wxArrayString parts = wxSplit( f.GetText(), ':' ); wxArrayString parts = wxSplit( f.GetText(), ':' );
*token = parts[0]; *token = parts[ 0 ];
return true; return true;
} }
else if( token->IsSameAs( wxT( "FOOTPRINT_NAME" ) ) ) else if( token->IsSameAs( wxT( "FOOTPRINT_NAME" ) ))
{ {
SCH_FIELD& f = component->GetFields()[ FOOTPRINT ]; SCH_FIELD& f = component->GetFields()[ FOOTPRINT ];
wxArrayString parts = wxSplit( f.GetText(), ':' ); wxArrayString parts = wxSplit( f.GetText(), ':' );
*token = parts[ std::min( 1, (int) parts.size() - 1 ) ]; *token = parts[ std::min( 1, (int) parts.size() - 1 ) ];
return true; return true;
} }
else if( token->IsSameAs( wxT( "UNIT" ) ) ) else if( token->IsSameAs( wxT( "UNIT" ) ))
{ {
*token = LIB_PART::SubReference( component->GetUnit() ); *token = LIB_PART::SubReference( component->GetUnit());
return true; return true;
} }
return false; return false;
}; };
auto sheetResolver = [ & ]( wxString* token ) -> bool std::function<bool( wxString* )> sheetResolver =
{ [&]( wxString* token ) -> bool
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( m_Parent ); {
std::vector<SCH_FIELD>& fields = sheet->GetFields(); SCH_SHEET* sheet = static_cast<SCH_SHEET*>( m_Parent );
std::vector<SCH_FIELD>& fields = sheet->GetFields();
for( int i = 0; i < SHEET_MANDATORY_FIELDS; ++i ) for( int i = 0; i < SHEET_MANDATORY_FIELDS; ++i )
{ {
if( token->IsSameAs( fields[i].GetCanonicalName().Upper() ) ) if( token->IsSameAs( fields[ i ].GetCanonicalName().Upper()))
{ {
// silently drop recursive references // silently drop recursive references
if( &fields[i] == this ) if( &fields[ i ] == this )
*token = wxEmptyString; *token = wxEmptyString;
else else
*token = fields[i].GetShownText(); *token = fields[ i ].GetShownText();
return true; return true;
} }
} }
for( size_t i = SHEET_MANDATORY_FIELDS; i < fields.size(); ++i ) for( size_t i = SHEET_MANDATORY_FIELDS; i < fields.size(); ++i )
{ {
if( token->IsSameAs( fields[i].GetName() ) ) if( token->IsSameAs( fields[ i ].GetName()))
{ {
// silently drop recursive references // silently drop recursive references
if( &fields[i] == this ) if( &fields[ i ] == this )
*token = wxEmptyString; *token = wxEmptyString;
else else
*token = fields[i].GetShownText(); *token = fields[ i ].GetShownText();
return true; return true;
} }
} }
return false; return false;
}; };
PROJECT* project = nullptr; PROJECT* project = nullptr;
wxString text = EDA_TEXT::GetShownText(); wxString text = EDA_TEXT::GetShownText();
@ -176,9 +178,9 @@ wxString SCH_FIELD::GetShownText() const
project = &g_RootSheet->GetScreen()->Kiway().Prj(); project = &g_RootSheet->GetScreen()->Kiway().Prj();
if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T ) if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T )
text = ExpandTextVars( text, symbolResolver, project ); text = ExpandTextVars( text, &symbolResolver, project );
else if( m_Parent && m_Parent->Type() == SCH_SHEET_T ) else if( m_Parent && m_Parent->Type() == SCH_SHEET_T )
text = ExpandTextVars( text, sheetResolver, project ); text = ExpandTextVars( text, &sheetResolver, project );
// WARNING: the IDs of FIELDS and SHEETS overlap, so one must check *both* the // WARNING: the IDs of FIELDS and SHEETS overlap, so one must check *both* the
// id and the parent's type. // id and the parent's type.

View File

@ -246,7 +246,6 @@ COLOR4D SCH_PAINTER::getRenderColor( const EDA_ITEM* aItem, int aLayer, bool aDr
else if( aItem->Type() == SCH_SHEET_T ) else if( aItem->Type() == SCH_SHEET_T )
{ {
SCH_SHEET* sheet = (SCH_SHEET*) aItem; SCH_SHEET* sheet = (SCH_SHEET*) aItem;
COLOR4D sheetColor = COLOR4D::UNSPECIFIED;
// Lazy fixup of legacy sheets with no color specifications // Lazy fixup of legacy sheets with no color specifications
if( sheet->GetBorderColor() == COLOR4D::UNSPECIFIED ) if( sheet->GetBorderColor() == COLOR4D::UNSPECIFIED )

View File

@ -452,50 +452,51 @@ wxString getElectricalTypeLabel( PINSHEETLABEL_SHAPE aType )
wxString SCH_TEXT::GetShownText() const wxString SCH_TEXT::GetShownText() const
{ {
auto textResolver = [this]( wxString* token ) -> bool std::function<bool( wxString* )> textResolver =
[this]( wxString* token ) -> bool
{
if( ( Type() == SCH_GLOBAL_LABEL_T
|| Type() == SCH_HIER_LABEL_T
|| Type() == SCH_SHEET_PIN_T )
&& token->IsSameAs( wxT( "CONNECTION_TYPE" ) ) )
{
*token = getElectricalTypeLabel( GetShape() );
return true;
}
if( Type() == SCH_SHEET_PIN_T && m_Parent )
{
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( m_Parent );
std::vector<SCH_FIELD>& fields = sheet->GetFields();
for( int i = 0; i < SHEET_MANDATORY_FIELDS; ++i )
{
if( token->IsSameAs( fields[i].GetCanonicalName().Upper() ) )
{ {
if( ( Type() == SCH_GLOBAL_LABEL_T *token = fields[i].GetShownText();
|| Type() == SCH_HIER_LABEL_T return true;
|| Type() == SCH_SHEET_PIN_T ) }
&& token->IsSameAs( wxT( "CONNECTION_TYPE" ) ) ) }
{
*token = getElectricalTypeLabel( GetShape() );
return true;
}
if( Type() == SCH_SHEET_PIN_T && m_Parent ) for( size_t i = SHEET_MANDATORY_FIELDS; i < fields.size(); ++i )
{ {
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( m_Parent ); if( token->IsSameAs( fields[i].GetName() ) )
std::vector<SCH_FIELD>& fields = sheet->GetFields(); {
*token = fields[i].GetShownText();
return true;
}
}
}
for( int i = 0; i < SHEET_MANDATORY_FIELDS; ++i ) return false;
{ };
if( token->IsSameAs( fields[i].GetCanonicalName().Upper() ) )
{
*token = fields[i].GetShownText();
return true;
}
}
for( size_t i = SHEET_MANDATORY_FIELDS; i < fields.size(); ++i )
{
if( token->IsSameAs( fields[i].GetName() ) )
{
*token = fields[i].GetShownText();
return true;
}
}
}
return false;
};
PROJECT* project = nullptr; PROJECT* project = nullptr;
if( g_RootSheet && g_RootSheet->GetScreen() ) if( g_RootSheet && g_RootSheet->GetScreen() )
project = &g_RootSheet->GetScreen()->Kiway().Prj(); project = &g_RootSheet->GetScreen()->Kiway().Prj();
return ExpandTextVars( EDA_TEXT::GetShownText(), textResolver, project ); return ExpandTextVars( EDA_TEXT::GetShownText(), &textResolver, project );
} }

View File

@ -283,11 +283,7 @@ int EE_INSPECTION_TOOL::ShowDatasheet( const TOOL_EVENT& aEvent )
} }
if( !datasheet.IsEmpty() && datasheet != wxT( "~" ) ) if( !datasheet.IsEmpty() && datasheet != wxT( "~" ) )
{ GetAssociatedDocument( m_frame, datasheet, &m_frame->Prj() );
SEARCH_STACK* lib_search = m_frame->Prj().SchSearchS();
GetAssociatedDocument( m_frame, datasheet, lib_search );
}
return 0; return 0;
} }

View File

@ -305,25 +305,26 @@ bool EnsureFileDirectoryExists( wxFileName* aTargetFullFileName,
const wxString PrePendPath( const wxString& aEnvVar, const wxString& aPriorityPath ); const wxString PrePendPath( const wxString& aEnvVar, const wxString& aPriorityPath );
/** /**
* Replace any environment variable references with their values. * Replace any environment variable & text variable references with their values.
* *
* @param aString = a string containing (perhaps) references to env var * @param aString = a string containing (perhaps) references to env var
* @return a string where env var are replaced by their value * @return a string where env var are replaced by their value
*/ */
const wxString ExpandEnvVarSubstitutions( const wxString& aString ); const wxString ExpandEnvVarSubstitutions( const wxString& aString, PROJECT* aProject );
/** /**
* Expand '${var-name}' templates in text. The LocalResolver is given first crack at it, * Expand '${var-name}' templates in text. The LocalResolver is given first crack at it,
* after which the PROJECT's resolver is called. * after which the PROJECT's resolver is called.
*/ */
wxString ExpandTextVars( const wxString& aSource, wxString ExpandTextVars( const wxString& aSource,
const std::function<bool( wxString* )>& aLocalResolver, const std::function<bool( wxString* )>* aLocalResolver,
const PROJECT* aProject ); const PROJECT* aProject );
/** /**
* Replace any environment variables in file-path uris (leaving network-path URIs alone). * Replace any environment and/or text variables in file-path uris (leaving network-path URIs
* alone).
*/ */
const wxString ResolveUriByEnvVars( const wxString& aUri ); const wxString ResolveUriByEnvVars( const wxString& aUri, PROJECT* aProject );
#ifdef __WXMAC__ #ifdef __WXMAC__

View File

@ -47,12 +47,10 @@ bool KeywordMatch( const wxString& aKeys, const wxString& aDatabase );
* @param aParent = main frame * @param aParent = main frame
* @param aDocName = filename of file to open (Full filename or short filename) * @param aDocName = filename of file to open (Full filename or short filename)
* if \a aDocName begins with http: or ftp: or www. the default internet browser is launched * if \a aDocName begins with http: or ftp: or www. the default internet browser is launched
* @param aPaths = a wxPathList to explore.
* if NULL or aDocName is a full filename, aPath is not used.
*/ */
bool GetAssociatedDocument( wxWindow* aParent, bool GetAssociatedDocument( wxWindow* aParent,
const wxString& aDocName, const wxString& aDocName,
const wxPathList* aPaths = NULL ); PROJECT* aProject );
#endif /* __INCLUDE__EDA_DOC_H__ */ #endif /* __INCLUDE__EDA_DOC_H__ */

View File

@ -51,11 +51,12 @@ struct SEARCH_PATH
class FILENAME_RESOLVER class FILENAME_RESOLVER
{ {
private: private:
wxString m_ConfigDir; // 3D configuration directory wxString m_ConfigDir; // 3D configuration directory
std::list< SEARCH_PATH > m_Paths; // list of base paths to search from std::list<SEARCH_PATH> m_Paths; // list of base paths to search from
int m_errflags; int m_errflags;
PGM_BASE* m_pgm; PGM_BASE* m_pgm;
wxString m_curProjDir; PROJECT* m_project;
wxString m_curProjDir;
/** /**
* Function createPathList * Function createPathList
@ -126,7 +127,8 @@ public:
* @retval true success * @retval true success
* @retval false failure * @retval false failure
*/ */
bool SetProjectDir( const wxString& aProjDir, bool* flgChanged = NULL ); bool SetProject( PROJECT* aProject, bool* flgChanged = NULL );
wxString GetProjectDir( void ); wxString GetProjectDir( void );
/** /**

View File

@ -477,15 +477,6 @@ public:
*/ */
static UTF8 FormatOptions( const PROPERTIES* aProperties ); static UTF8 FormatOptions( const PROPERTIES* aProperties );
/**
* Replaces any environment variable references with their values and is here to fully
* embellish the TABLE_ROW::uri in a platform independent way.
*
* This enables library tables to have platform dependent environment variables in them,
* allowing for a uniform table across platforms.
*/
static const wxString ExpandSubstitutions( const wxString& aString );
protected: protected:
/** /**

View File

@ -66,18 +66,19 @@ wxString TEXTE_PCB::GetShownText() const
const BOARD* board = static_cast<BOARD*>( GetParent() ); const BOARD* board = static_cast<BOARD*>( GetParent() );
wxASSERT( board ); wxASSERT( board );
auto moduleResolver = [ this ]( wxString* token ) -> bool std::function<bool( wxString* )> moduleResolver =
{ [ this ]( wxString* token ) -> bool
if( token->IsSameAs( wxT( "LAYER" ) ) ) {
{ if( token->IsSameAs( wxT( "LAYER" ) ) )
*token = GetLayerName(); {
return true; *token = GetLayerName();
} return true;
}
return false; return false;
}; };
return ExpandTextVars( EDA_TEXT::GetShownText(), moduleResolver, board->GetProject() ); return ExpandTextVars( EDA_TEXT::GetShownText(), &moduleResolver, board->GetProject() );
} }

View File

@ -496,29 +496,30 @@ wxString TEXTE_MODULE::GetShownText() const
const BOARD* board = static_cast<BOARD*>( module->GetParent() ); const BOARD* board = static_cast<BOARD*>( module->GetParent() );
wxASSERT( board ); wxASSERT( board );
auto moduleResolver = [ this, module ]( wxString* token ) -> bool std::function<bool( wxString* )> moduleResolver =
{ [ this, module ]( wxString* token ) -> bool
if( module ) {
{ if( module )
if( token->IsSameAs( wxT( "REFERENCE" ) ) ) {
{ if( token->IsSameAs( wxT( "REFERENCE" ) ))
*token = module->GetReference(); {
return true; *token = module->GetReference();
} return true;
else if( token->IsSameAs( wxT( "VALUE" ) ) ) }
{ else if( token->IsSameAs( wxT( "VALUE" ) ))
*token = module->GetValue(); {
return true; *token = module->GetValue();
} return true;
else if( token->IsSameAs( wxT( "LAYER" ) ) ) }
{ else if( token->IsSameAs( wxT( "LAYER" ) ))
*token = GetLayerName(); {
return true; *token = GetLayerName();
} return true;
} }
}
return false; return false;
}; };
return ExpandTextVars( EDA_TEXT::GetShownText(), moduleResolver, board->GetProject() ); return ExpandTextVars( EDA_TEXT::GetShownText(), &moduleResolver, board->GetProject() );
} }

View File

@ -395,7 +395,7 @@ void GITHUB_PLUGIN::cacheLib( const wxString& aLibraryPath, const PROPERTIES* aP
{ {
wxString wx_pretty_dir = pretty_dir; wxString wx_pretty_dir = pretty_dir;
wx_pretty_dir = LIB_TABLE::ExpandSubstitutions( wx_pretty_dir ); wx_pretty_dir = ExpandEnvVarSubstitutions( wx_pretty_dir, nullptr );
wxFileName wx_pretty_fn = wx_pretty_dir; wxFileName wx_pretty_fn = wx_pretty_dir;