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();
void SetSHA1( const unsigned char* aSHA1Sum );
const wxString GetCacheBaseName( void );
const wxString GetCacheBaseName();
wxDateTime modTime; // file modification time
unsigned char sha1sum[20];
@ -155,8 +155,7 @@ S3D_CACHE_ENTRY::S3D_CACHE_ENTRY()
S3D_CACHE_ENTRY::~S3D_CACHE_ENTRY()
{
if( NULL != sceneData )
delete sceneData;
delete sceneData;
if( NULL != renderData )
S3D::Destroy3DModel( &renderData );
@ -174,11 +173,10 @@ void S3D_CACHE_ENTRY::SetSHA1( const unsigned char* aSHA1Sum )
}
memcpy( sha1sum, aSHA1Sum, 20 );
return;
}
const wxString S3D_CACHE_ENTRY::GetCacheBaseName( void )
const wxString S3D_CACHE_ENTRY::GetCacheBaseName()
{
if( m_CacheBaseName.empty() )
m_CacheBaseName = sha1ToWXString( sha1sum );
@ -189,11 +187,9 @@ const wxString S3D_CACHE_ENTRY::GetCacheBaseName( void )
S3D_CACHE::S3D_CACHE()
{
m_DirtyCache = false;
m_FNResolver = new FILENAME_RESOLVER;
m_project = nullptr;
m_Plugins = new S3D_PLUGIN_MANAGER;
return;
}
@ -201,13 +197,8 @@ S3D_CACHE::~S3D_CACHE()
{
FlushCache();
if( m_FNResolver )
delete m_FNResolver;
if( m_Plugins )
delete m_Plugins;
return;
delete m_FNResolver;
delete m_Plugins;
}
@ -514,12 +505,7 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
if( !m_ConfigDir.empty() )
return false;
wxFileName cfgdir;
if( aConfigDir.StartsWith( "${" ) || aConfigDir.StartsWith( "$(" ) )
cfgdir.Assign( ExpandEnvVarSubstitutions( aConfigDir ), "" );
else
cfgdir.Assign( aConfigDir, "" );
wxFileName cfgdir( ExpandEnvVarSubstitutions( aConfigDir, m_project ), "" );
cfgdir.Normalize();
@ -564,7 +550,7 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
#elif defined(__APPLE)
cacheDir = "${HOME}/Library/Caches/kicad/3d";
#else // assume Linux
cacheDir = ExpandEnvVarSubstitutions( "${XDG_CACHE_HOME}" );
cacheDir = ExpandEnvVarSubstitutions( "${XDG_CACHE_HOME}", nullptr );
if( cacheDir.empty() || cacheDir == "${XDG_CACHE_HOME}" )
cacheDir = "${HOME}/.cache";
@ -572,7 +558,7 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
cacheDir.append( "/kicad/3d" );
#endif
cacheDir = ExpandEnvVarSubstitutions( cacheDir );
cacheDir = ExpandEnvVarSubstitutions( cacheDir, m_project );
cfgdir.Assign( cacheDir, "" );
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 )
return m_ConfigDir;
m_project = aProject;
// 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;
if( m_FNResolver->SetProjectDir( aProjDir, &hasChanged ) && hasChanged )
if( m_FNResolver->SetProject( aProject, &hasChanged ) && hasChanged )
{
m_CacheMap.clear();
@ -677,23 +610,16 @@ bool S3D_CACHE::SetProjectDir( const wxString& aProjDir )
void S3D_CACHE::SetProgramBase( PGM_BASE* aBase )
{
m_FNResolver->SetProgramBase( aBase );
return;
}
wxString S3D_CACHE::GetProjectDir( void )
{
return m_FNResolver->GetProjectDir();
}
FILENAME_RESOLVER* S3D_CACHE::GetResolver( void )
FILENAME_RESOLVER* S3D_CACHE::GetResolver()
{
return m_FNResolver;
}
std::list< wxString > const* S3D_CACHE::GetFileFilters( void ) const
std::list< wxString > const* S3D_CACHE::GetFileFilters() const
{
return m_Plugins->GetFileFilters();
}
@ -715,17 +641,13 @@ void S3D_CACHE::FlushCache( bool closePlugins )
if( closePlugins )
ClosePlugins();
return;
}
void S3D_CACHE::ClosePlugins( void )
void S3D_CACHE::ClosePlugins()
{
if( NULL != m_Plugins )
if( m_Plugins )
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 )
{
std::lock_guard<std::mutex> lock( mutex3D_cacheManager );
@ -805,7 +702,7 @@ S3D_CACHE* PROJECT::Get3DCacheManager( bool aUpdateProjDir )
}
if( aUpdateProjDir )
cache->SetProjectDir( GetProjectPath() );
cache->SetProject( this );
return cache;
}

View File

@ -60,23 +60,13 @@ private:
/// mapping of file names to cache names and data
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;
/// set true if the cache needs to be updated
bool m_DirtyCache;
/// 3D cache directory
wxString m_CacheDir;
/// base configuration path for 3D items
wxString m_ConfigDir;
/// current KiCad project dir
wxString m_ProjDir;
PROJECT* m_project;
wxString m_CacheDir;
wxString m_ConfigDir; /// base configuration path for 3D items
/** Find or create cache entry for file name
*
@ -133,22 +123,12 @@ public:
*/
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
* sets the current project's working directory; this
* affects the model search path
*/
bool SetProjectDir( const wxString& aProjDir );
bool SetProject( PROJECT* aProject );
/**
* Function SetProgramBase
@ -158,12 +138,6 @@ public:
*/
void SetProgramBase( PGM_BASE* aBase );
/**
* Function GetProjectDir
* returns the current project's working directory
*/
wxString GetProjectDir( void );
/**
* Function Load
* attempts to load the scene data for a model; it will consult the
@ -177,7 +151,7 @@ public:
*/
SCENEGRAPH* Load( const wxString& aModelFile );
FILENAME_RESOLVER* GetResolver( void );
FILENAME_RESOLVER* GetResolver();
/**
* Function GetFileFilters
@ -186,7 +160,7 @@ public:
*
* @return a pointer to the filter list
*/
std::list< wxString > const* GetFileFilters( void ) const;
std::list< wxString > const* GetFileFilters() const;
/**
* Function FlushCache
@ -198,7 +172,7 @@ public:
* Function ClosePlugins
* unloads plugins to free memory
*/
void ClosePlugins( void );
void ClosePlugins();
/**
* Function GetModel
@ -209,8 +183,6 @@ public:
* @return is a pointer to the render data or NULL if not available
*/
S3DMODEL* GetModel( const wxString& aModelFileName );
wxString GetModelHash( const wxString& aModelFileName );
};
#endif // CACHE_3D_H

View File

@ -340,12 +340,7 @@ void S3D_PLUGIN_MANAGER::checkPluginName( const wxString& aPath,
if( aPath.empty() || !wxFileName::FileExists( aPath ) )
return;
wxFileName path;
if( aPath.StartsWith( "${" ) || aPath.StartsWith( "$(" ) )
path.Assign( ExpandEnvVarSubstitutions( aPath ) );
else
path.Assign( aPath );
wxFileName path( ExpandEnvVarSubstitutions( aPath, nullptr ) );
path.Normalize();
@ -374,7 +369,7 @@ void S3D_PLUGIN_MANAGER::checkPluginName( 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
if( aPath.empty() )
@ -388,7 +383,7 @@ void S3D_PLUGIN_MANAGER::checkPluginPath( const wxString& aPath,
wxFileName path;
if( aPath.StartsWith( "${" ) || aPath.StartsWith( "$(" ) )
path.Assign( ExpandEnvVarSubstitutions( aPath ), "" );
path.Assign( ExpandEnvVarSubstitutions( aPath, nullptr ), "" );
else
path.Assign( aPath, "" );

View File

@ -373,7 +373,7 @@ enum Bracket
wxString ExpandTextVars( const wxString& aSource,
const std::function<bool( wxString* )>& aLocalResolver,
const std::function<bool( wxString* )>* aLocalResolver,
const PROJECT* aProject )
{
wxString newbuf;
@ -396,7 +396,11 @@ wxString ExpandTextVars( const wxString& aSource,
if( token.IsEmpty() )
continue;
if( aLocalResolver( &token ) || ( aProject && aProject->TextVarResolver( &token ) ) )
if( aLocalResolver && (*aLocalResolver)( &token ) )
{
newbuf.append( token );
}
else if( aProject && aProject->TextVarResolver( &token ) )
{
newbuf.append( token );
}
@ -419,7 +423,7 @@ wxString ExpandTextVars( const wxString& aSource,
//
// 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();
@ -477,9 +481,14 @@ wxString KIwxExpandEnvVars(const wxString& str)
// NB: use wxGetEnv instead of wxGetenv as otherwise variables
// set through wxSetEnv may not be read correctly!
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;
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.
// 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 );
// 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.
wxURL url( aUri );
wxURL url( uri );
if( url.GetError() == wxURL_NOERR )
return aUri;
return uri;
// Otherwise, the path points to a local file. Resolve environment
// variables if any.
return ExpandEnvVarSubstitutions( aUri );
// Otherwise, the path points to a local file. Resolve environment variables if any.
return ExpandEnvVarSubstitutions( aUri, aProject );
}

View File

@ -77,15 +77,18 @@ static const wxFileTypeInfo EDAfallbacks[] =
};
bool GetAssociatedDocument( wxWindow* aParent,
const wxString& aDocName,
const wxPathList* aPaths)
bool GetAssociatedDocument( wxWindow* aParent, const wxString& aDocName, PROJECT* aProject )
{
wxString docname, fullfilename;
wxString msg;
wxString command;
bool success = false;
SEARCH_STACK* aPaths = nullptr;
wxString docname;
wxString fullfilename;
wxString msg;
wxString command;
bool success = false;
#if defined(EESCHEMA)
SEARCH_STACK* aPaths = aProject ? aProject->SchSearchS() : nullptr;
#endif
// Is an internet url
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
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 );
wxLaunchDefaultBrowser( uri.BuildURI() );
@ -117,7 +120,7 @@ bool GetAssociatedDocument( wxWindow* aParent,
/* Compute the full file name */
if( wxIsAbsolutePath( docname ) || aPaths == NULL)
if( wxIsAbsolutePath( docname ) || aPaths == NULL )
fullfilename = docname;
/* 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
@ -126,9 +129,7 @@ bool GetAssociatedDocument( wxWindow* aParent,
else if( wxFileName::FileExists( docname ) )
fullfilename = docname;
else
{
fullfilename = aPaths->FindValidPath( docname );
}
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 );
FILENAME_RESOLVER::FILENAME_RESOLVER()
FILENAME_RESOLVER::FILENAME_RESOLVER() :
m_pgm( nullptr ),
m_project( nullptr )
{
m_errflags = 0;
m_pgm = NULL;
}
@ -62,12 +63,7 @@ bool FILENAME_RESOLVER::Set3DConfigDir( const wxString& aConfigDir )
if( aConfigDir.empty() )
return false;
wxFileName cfgdir;
if( aConfigDir.StartsWith( "${" ) || aConfigDir.StartsWith( "$(" ) )
cfgdir.Assign( ExpandEnvVarSubstitutions( aConfigDir ), "" );
else
cfgdir.Assign( aConfigDir, "" );
wxFileName cfgdir( ExpandEnvVarSubstitutions( aConfigDir, m_project ), "" );
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;
wxFileName projdir;
if( aProjDir.StartsWith( "${" ) || aProjDir.StartsWith( "$(" ) )
projdir.Assign( ExpandEnvVarSubstitutions( aProjDir ), "" );
else
projdir.Assign( aProjDir, "" );
wxFileName projdir( ExpandEnvVarSubstitutions( aProject->GetProjectPath(), aProject ), "" );
projdir.Normalize();
@ -113,7 +106,6 @@ bool FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgChange
if( flgChanged )
*flgChanged = true;
}
else
{
@ -123,7 +115,6 @@ bool FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgChange
if( flgChanged )
*flgChanged = true;
}
else
{
@ -132,13 +123,13 @@ bool FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgChange
}
#ifdef DEBUG
do {
{
std::ostringstream ostr;
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
ostr << " * [INFO] changed project dir to ";
ostr << m_Paths.front().m_pathexp.ToUTF8();
wxLogTrace( MASK_3D_RESOLVER, "%s\n", ostr.str().c_str() );
} while( 0 );
}
#endif
return true;
@ -188,7 +179,7 @@ bool FILENAME_RESOLVER::createPathList()
{
for( const wxString& curr_path : epaths )
{
wxString pathVal = ExpandEnvVarSubstitutions( curr_path );
wxString pathVal = ExpandEnvVarSubstitutions( curr_path, m_project );
if( pathVal.empty() )
{
@ -272,8 +263,7 @@ wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
// wxFileName::Normalize() routine to perform expansion then
// we will have a race condition since wxWidgets does not assure
// a threadsafe wrapper for getenv().
if( tname.StartsWith( "${" ) || tname.StartsWith( "$(" ) )
tname = ExpandEnvVarSubstitutions( tname );
tname = ExpandEnvVarSubstitutions( tname, m_project );
wxFileName tmpFN( tname );
@ -341,8 +331,7 @@ wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
tmpFN.Assign( sPL->m_pathexp, "" );
wxString fullPath = tmpFN.GetPathWithSep() + tname;
if( fullPath.StartsWith( "${" ) || fullPath.StartsWith( "$(" ) )
fullPath = ExpandEnvVarSubstitutions( fullPath );
fullPath = ExpandEnvVarSubstitutions( fullPath, m_project );
if( wxFileName::FileExists( fullPath ) )
{
@ -361,7 +350,7 @@ wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
wxString fullPath( "${KISYS3DMOD}" );
fullPath.Append( fpath.GetPathSeparator() );
fullPath.Append( tname );
fullPath = ExpandEnvVarSubstitutions( fullPath );
fullPath = ExpandEnvVarSubstitutions( fullPath, m_project );
fpath.Assign( fullPath );
if( fpath.Normalize() && fpath.FileExists() )
@ -404,8 +393,7 @@ wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
wxFileName fpath( wxFileName::DirName( sPL->m_pathexp ) );
wxString fullPath = fpath.GetPathWithSep() + relpath;
if( fullPath.StartsWith( "${") || fullPath.StartsWith( "$(" ) )
fullPath = ExpandEnvVarSubstitutions( fullPath );
fullPath = ExpandEnvVarSubstitutions( fullPath, m_project );
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 );
#endif
wxFileName path;
if( tpath.m_pathvar.StartsWith( "${" ) || tpath.m_pathvar.StartsWith( "$(" ) )
path.Assign( ExpandEnvVarSubstitutions( tpath.m_pathvar ), "" );
else
path.Assign( tpath.m_pathvar, "" );
wxFileName path( ExpandEnvVarSubstitutions( tpath.m_pathvar, m_project ), "" );
path.Normalize();
@ -728,12 +711,7 @@ void FILENAME_RESOLVER::checkEnvVarPath( const wxString& aPath )
SEARCH_PATH lpath;
lpath.m_alias = envar;
lpath.m_pathvar = lpath.m_alias;
wxFileName tmpFN;
if( lpath.m_alias.StartsWith( "${" ) || lpath.m_alias.StartsWith( "$(" ) )
tmpFN.Assign( ExpandEnvVarSubstitutions( lpath.m_alias ), "" );
else
tmpFN.Assign( lpath.m_alias, "" );
wxFileName tmpFN( ExpandEnvVarSubstitutions( lpath.m_alias, m_project ), "" );
wxUniChar psep = tmpFN.GetPathSeparator();
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
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() )
{

View File

@ -74,7 +74,7 @@ const wxString LIB_TABLE_ROW::GetFullURI( bool aSubstituted ) const
return uri_expanded;
#else // late expansion
return LIB_TABLE::ExpandSubstitutions( uri_user );
return ExpandEnvVarSubstitutions( uri_user, nullptr );
#endif
}
@ -449,9 +449,3 @@ UTF8 LIB_TABLE::FormatOptions( const PROPERTIES* aProperties )
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& aProjectPath )
{
wxString fullFileName = ExpandEnvVarSubstitutions( aShortFileName );
wxString fullFileName = ExpandEnvVarSubstitutions( aShortFileName, nullptr );
if( fullFileName.IsEmpty() )
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
wxString WS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase )
{
auto wsResolver = [ this ]( wxString* token ) -> bool
{
if( token->IsSameAs( wxT( "KICAD_VERSION" ) ) )
{
*token = wxString::Format( wxT( "%s%s %s" ),
productName,
Pgm().App().GetAppName(),
GetBuildVersion() );
return true;
}
else if( token->IsSameAs( wxT( "#" ) ) )
{
*token = wxString::Format( wxT( "%d" ), m_sheetNumber );
return true;
}
else if( token->IsSameAs( wxT( "##" ) ) )
{
*token = wxString::Format( wxT( "%d" ), m_sheetCount );
return true;
}
else if( token->IsSameAs( wxT( "SHEETNAME" ) ) )
{
*token = m_sheetFullName;
return true;
}
else if( token->IsSameAs( wxT( "FILENAME" ) ) )
{
wxFileName fn( m_fileName );
*token = fn.GetFullName();
return true;
}
else if( token->IsSameAs( wxT( "PAPER" ) ) )
{
*token = m_paperFormat ? *m_paperFormat : wxString("");
return true;
}
else if( token->IsSameAs( wxT( "LAYER" ) ) )
{
*token = m_sheetLayer ? *m_sheetLayer : wxString("");
return true;
}
else if( token->IsSameAs( wxT( "ISSUE_DATE" ) ) )
{
*token = m_titleBlock ? m_titleBlock->GetDate() : wxString("");
return true;
}
else if( token->IsSameAs( wxT( "REVISION" ) ) )
{
*token = m_titleBlock ? m_titleBlock->GetRevision() : wxString("");
return true;
}
else if( token->IsSameAs( wxT( "TITLE" ) ) )
{
*token = m_titleBlock ? m_titleBlock->GetTitle() : wxString("");
return true;
}
else if( token->IsSameAs( wxT( "COMPANY" ) ) )
{
*token = m_titleBlock ? m_titleBlock->GetCompany() : wxString("");
return true;
}
else if( token->Left( token->Len()-1 ).IsSameAs( wxT( "COMMENT" ) ) )
{
wxChar c = token->Last();
std::function<bool( wxString* )> wsResolver =
[ this ]( wxString* token ) -> bool
{
if( token->IsSameAs( wxT( "KICAD_VERSION" ) ))
{
*token = wxString::Format( wxT( "%s%s %s" ),
productName,
Pgm().App().GetAppName(),
GetBuildVersion());
return true;
}
else if( token->IsSameAs( wxT( "#" ) ))
{
*token = wxString::Format( wxT( "%d" ), m_sheetNumber );
return true;
}
else if( token->IsSameAs( wxT( "##" ) ))
{
*token = wxString::Format( wxT( "%d" ), m_sheetCount );
return true;
}
else if( token->IsSameAs( wxT( "SHEETNAME" ) ))
{
*token = m_sheetFullName;
return true;
}
else if( token->IsSameAs( wxT( "FILENAME" ) ))
{
wxFileName fn( m_fileName );
*token = fn.GetFullName();
return true;
}
else if( token->IsSameAs( wxT( "PAPER" ) ))
{
*token = m_paperFormat ? *m_paperFormat : wxString( "" );
return true;
}
else if( token->IsSameAs( wxT( "LAYER" ) ))
{
*token = m_sheetLayer ? *m_sheetLayer : wxString( "" );
return true;
}
else if( token->IsSameAs( wxT( "ISSUE_DATE" ) ))
{
*token = m_titleBlock ? m_titleBlock->GetDate() : wxString( "" );
return true;
}
else if( token->IsSameAs( wxT( "REVISION" ) ))
{
*token = m_titleBlock ? m_titleBlock->GetRevision() : wxString( "" );
return true;
}
else if( token->IsSameAs( wxT( "TITLE" ) ))
{
*token = m_titleBlock ? m_titleBlock->GetTitle() : wxString( "" );
return true;
}
else if( token->IsSameAs( wxT( "COMPANY" ) ))
{
*token = m_titleBlock ? m_titleBlock->GetCompany() : wxString( "" );
return true;
}
else if( token->Left( token->Len() - 1 ).IsSameAs( wxT( "COMMENT" ) ))
{
wxChar c = token->Last();
switch( c )
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
*token = m_titleBlock ? m_titleBlock->GetComment( c - '0' )
: wxString("");
return true;
}
}
switch( c )
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
*token = m_titleBlock ? m_titleBlock->GetComment( c - '0' )
: wxString( "" );
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;
}

View File

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

View File

@ -97,7 +97,7 @@ protected:
else if (event.GetId() == MYID_SHOW_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
{

View File

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

View File

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

View File

@ -452,50 +452,51 @@ wxString getElectricalTypeLabel( PINSHEETLABEL_SHAPE aType )
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
|| Type() == SCH_HIER_LABEL_T
|| Type() == SCH_SHEET_PIN_T )
&& token->IsSameAs( wxT( "CONNECTION_TYPE" ) ) )
{
*token = getElectricalTypeLabel( GetShape() );
return true;
}
*token = fields[i].GetShownText();
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( size_t i = SHEET_MANDATORY_FIELDS; i < fields.size(); ++i )
{
if( token->IsSameAs( fields[i].GetName() ) )
{
*token = fields[i].GetShownText();
return true;
}
}
}
for( int i = 0; i < SHEET_MANDATORY_FIELDS; ++i )
{
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;
};
return false;
};
PROJECT* project = nullptr;
if( g_RootSheet && g_RootSheet->GetScreen() )
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( "~" ) )
{
SEARCH_STACK* lib_search = m_frame->Prj().SchSearchS();
GetAssociatedDocument( m_frame, datasheet, lib_search );
}
GetAssociatedDocument( m_frame, datasheet, &m_frame->Prj() );
return 0;
}

View File

@ -305,25 +305,26 @@ bool EnsureFileDirectoryExists( wxFileName* aTargetFullFileName,
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
* @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,
* after which the PROJECT's resolver is called.
*/
wxString ExpandTextVars( const wxString& aSource,
const std::function<bool( wxString* )>& aLocalResolver,
const std::function<bool( wxString* )>* aLocalResolver,
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__

View File

@ -47,12 +47,10 @@ bool KeywordMatch( const wxString& aKeys, const wxString& aDatabase );
* @param aParent = main frame
* @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
* @param aPaths = a wxPathList to explore.
* if NULL or aDocName is a full filename, aPath is not used.
*/
bool GetAssociatedDocument( wxWindow* aParent,
const wxString& aDocName,
const wxPathList* aPaths = NULL );
PROJECT* aProject );
#endif /* __INCLUDE__EDA_DOC_H__ */

View File

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

View File

@ -477,15 +477,6 @@ public:
*/
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:
/**

View File

@ -66,18 +66,19 @@ wxString TEXTE_PCB::GetShownText() const
const BOARD* board = static_cast<BOARD*>( GetParent() );
wxASSERT( board );
auto moduleResolver = [ this ]( wxString* token ) -> bool
{
if( token->IsSameAs( wxT( "LAYER" ) ) )
{
*token = GetLayerName();
return true;
}
std::function<bool( wxString* )> moduleResolver =
[ this ]( wxString* token ) -> bool
{
if( token->IsSameAs( wxT( "LAYER" ) ) )
{
*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() );
wxASSERT( board );
auto moduleResolver = [ this, module ]( wxString* token ) -> bool
{
if( module )
{
if( token->IsSameAs( wxT( "REFERENCE" ) ) )
{
*token = module->GetReference();
return true;
}
else if( token->IsSameAs( wxT( "VALUE" ) ) )
{
*token = module->GetValue();
return true;
}
else if( token->IsSameAs( wxT( "LAYER" ) ) )
{
*token = GetLayerName();
return true;
}
}
std::function<bool( wxString* )> moduleResolver =
[ this, module ]( wxString* token ) -> bool
{
if( module )
{
if( token->IsSameAs( wxT( "REFERENCE" ) ))
{
*token = module->GetReference();
return true;
}
else if( token->IsSameAs( wxT( "VALUE" ) ))
{
*token = module->GetValue();
return true;
}
else if( token->IsSameAs( wxT( "LAYER" ) ))
{
*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;
wx_pretty_dir = LIB_TABLE::ExpandSubstitutions( wx_pretty_dir );
wx_pretty_dir = ExpandEnvVarSubstitutions( wx_pretty_dir, nullptr );
wxFileName wx_pretty_fn = wx_pretty_dir;