42#define CFGFILE_VERSION 1
45#define ERRFLG_ALIAS (1)
46#define ERRFLG_RELPATH (2)
47#define ERRFLG_ENVPATH (4)
49#define MASK_3D_RESOLVER "3D_RESOLVER"
64 if( aConfigDir.empty() )
71 if( !cfgdir.DirExists() )
92 if( !projdir.DirExists() )
103 al.
m_Alias = wxS(
"${KIPRJMOD}" );
128 std::ostringstream ostr;
129 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
130 ostr <<
" * [INFO] changed project dir to ";
131 ostr <<
m_paths.front().m_Pathexp.ToUTF8();
169 lpath.
m_Alias = wxS(
"${KIPRJMOD}" );
174 wxUniChar psep = fndummy.GetPathSeparator();
175 std::list< wxString > epaths;
179 for(
const wxString& currPath : epaths )
181 wxString currPathVarFormat = currPath;
182 currPathVarFormat.Prepend( wxS(
"${" ) );
183 currPathVarFormat.Append( wxS(
"}" ) );
187 if( pathVal.empty() )
193 fndummy.Assign( pathVal,
"" );
208 lpath.
m_Alias = currPathVarFormat;
218 std::list< SEARCH_PATH >::const_iterator sPL =
m_paths.begin();
222 wxLogTrace(
MASK_3D_RESOLVER, wxS(
" + %s : '%s'\n" ), (*sPL).m_Alias.GetData(),
223 (*sPL).m_Pathexp.GetData() );
234 wxUniChar envMarker(
'$' );
236 while( !
m_paths.empty() && envMarker != *
m_paths.back().m_Alias.rbegin() )
251 if( aFileName.empty() )
252 return wxEmptyString;
258 wxString tname = aFileName;
271 wxLogTrace( wxT(
"KICAD_EMBED" ),
272 wxT(
"No EMBEDDED_FILES object provided for kicad_embed URI" ) );
273 return wxEmptyString;
276 wxString
path = tname.Mid( 14 );
279 if( !temp_file.IsOk() )
281 wxLogTrace( wxT(
"KICAD_EMBED" ),
282 wxT(
"Failed to get temp file '%s' for kicad_embed URI" ),
path );
283 return wxEmptyString;
286 wxLogTrace( wxT(
"KICAD_EMBED" ), wxT(
"Opening embedded file '%s' as '%s'" ),
287 tname, temp_file.GetFullPath() );
289 return temp_file.GetFullPath();
292 wxFileName tmpFN( tname );
296 if( tmpFN.FileExists() )
299 tname = tmpFN.GetFullPath();
303 if( aFileName.StartsWith( wxS(
"${" ) ) || aFileName.StartsWith( wxS(
"$(" ) ) )
311 if( aFileName.StartsWith(
"${" ) || aFileName.StartsWith(
"$(" ) )
316 wxString errmsg =
"[3D File Resolver] No such path; ensure the environment var is "
318 errmsg.append(
"\n" );
319 errmsg.append( tname );
320 errmsg.append(
"\n" );
324 return wxEmptyString;
336 if( !
m_paths.begin()->m_Pathexp.empty() && !tname.StartsWith(
":" ) )
338 tmpFN.Assign(
m_paths.begin()->m_Pathexp,
"" );
339 wxString fullPath = tmpFN.GetPathWithSep() + tname;
343 if( wxFileName::FileExists( fullPath ) )
345 tmpFN.Assign( fullPath );
347 tname = tmpFN.GetFullPath();
354 if( !aWorkingPath.IsEmpty() && !tname.StartsWith(
":" ) )
356 wxString tmp = aWorkingPath;
357 tmp.Append( tmpFN.GetPathSeparator() );
361 if( tmpFN.MakeAbsolute() && tmpFN.FileExists() )
363 tname = tmpFN.GetFullPath();
369 if( !tname.StartsWith( wxS(
":" ) ) )
372 wxString fullPath( wxString::Format( wxS(
"${%s}" ),
374 fullPath.Append( fpath.GetPathSeparator() );
375 fullPath.Append( tname );
377 fpath.Assign( fullPath );
381 tname = fpath.GetFullPath();
398 wxString errmsg =
"[3D File Resolver] No such path";
399 errmsg.append( wxS(
"\n" ) );
400 errmsg.append( tname );
401 errmsg.append( wxS(
"\n" ) );
405 return wxEmptyString;
411 if(
path.m_Alias.StartsWith( wxS(
"${" ) ) ||
path.m_Alias.StartsWith( wxS(
"$(" ) ) )
414 if(
path.m_Alias == alias && !
path.m_Pathexp.empty() )
416 wxFileName fpath( wxFileName::DirName(
path.m_Pathexp ) );
417 wxString fullPath = fpath.GetPathWithSep() + relpath;
421 if( wxFileName::FileExists( fullPath ) )
425 wxFileName tmp( fullPath );
428 tname = tmp.GetFullPath();
438 wxString errmsg =
"[3D File Resolver] No such path; ensure the path alias is defined";
439 errmsg.append(
"\n" );
440 errmsg.append( tname.substr( 1 ) );
441 errmsg.append(
"\n" );
445 return wxEmptyString;
459 while( tpath.
m_Pathvar.EndsWith( wxT(
"\\" ) ) )
470 if( !
path.DirExists() )
472 wxString versionedPath = wxString::Format( wxS(
"${%s}" ),
477 || aPath.
m_Pathvar == wxS(
"${KISYS3DMOD}" )
478 || aPath.
m_Pathvar == wxS(
"$(KISYS3DMOD)" ) )
484 wxString msg =
_(
"The given path does not exist" );
485 msg.append( wxT(
"\n" ) );
497 while( tpath.
m_Pathexp.EndsWith( wxT(
"\\" ) ) )
505 std::list< SEARCH_PATH >::iterator sPL =
m_paths.begin();
506 std::list< SEARCH_PATH >::iterator ePL =
m_paths.end();
510 if( tpath.
m_Alias == sPL->m_Alias )
512 wxString msg =
_(
"Alias: " );
514 msg.append( wxT(
"\n" ) );
515 msg.append(
_(
"This path:" ) + wxS(
" " ) );
517 msg.append( wxT(
"\n" ) );
518 msg.append(
_(
"Existing path:" ) + wxS(
" " ) );
519 msg.append( sPL->m_Pathvar );
534 bool useParen =
false;
536 if( aPath.StartsWith( wxS(
"$(" ) ) )
538 else if( !aPath.StartsWith( wxS(
"${" ) ) )
544 pEnd = aPath.find( wxS(
")" ) );
546 pEnd = aPath.find( wxS(
"}" ) );
548 if( pEnd == wxString::npos )
551 wxString envar = aPath.substr( 0, pEnd + 1 );
560 if( sPL->m_Alias == envar )
563 if( !sPL->m_Alias.StartsWith( wxS(
"${" ) ) )
574 wxUniChar psep = tmpFN.GetPathSeparator();
577 if( !tmpFN.DirExists() )
594 wxString fname = aFullPathName;
601 std::list< SEARCH_PATH >::const_iterator sL =
m_paths.begin();
608 if( sL->m_Pathexp.empty() )
617 if( sL->m_Alias.StartsWith( wxS(
"${" ) ) || sL->m_Alias.StartsWith( wxS(
"$(" ) ) )
627 fpath.Assign( tpath, wxT(
"" ) );
631 fpath.Assign( sL->m_Pathexp, wxT(
"" ) );
634 wxString fps = fpath.GetPathWithSep();
637 idx = fname.find( fps );
641 fname = fname.substr( fps.size() );
645 fname.Replace( wxT(
"\\" ), wxT(
"/" ) );
648 if( sL->m_Alias.StartsWith( wxS(
"${" ) ) || sL->m_Alias.StartsWith( wxS(
"$(" ) ) )
652 tname.Append( wxS(
"/" ) );
653 tname.append( fname );
659 tname.append( sL->m_Alias );
660 tname.append( wxS(
"}/" ) );
661 tname.append( fname );
675 fname.Replace( wxT(
"\\" ), wxT(
"/" ) );
689 wxString& anAlias, wxString& aRelPath )
const
694 size_t searchStart = 0;
696 if( aFileName.StartsWith( wxT(
":" ) ) )
699 size_t tagpos = aFileName.find( wxT(
":" ), searchStart );
701 if( tagpos == wxString::npos || tagpos == searchStart )
704 if( tagpos + 1 >= aFileName.length() )
707 anAlias = aFileName.substr( searchStart, tagpos - searchStart );
708 aRelPath = aFileName.substr( tagpos + 1 );
725 if( aFileName.empty() )
728 if( aFileName.StartsWith( wxT(
"file://" ) )
731 size_t prefixLength = aFileName.StartsWith( wxT(
"file://" ) ) ? 7 : 14;
732 if( aFileName.length() > prefixLength && aFileName[prefixLength] !=
'/' )
738 wxString filename = aFileName;
740 size_t aliasStart = aFileName.StartsWith(
':' ) ? 1 : 0;
741 size_t aliasEnd = aFileName.find(
':', aliasStart );
745 filename.Replace( wxT(
"/" ), wxT(
"\\" ) );
748 if( aliasEnd != wxString::npos )
750 size_t pos1 = filename.find( wxT(
":\\" ) );
752 if( pos1 != wxString::npos && ( pos1 != aliasEnd || pos1 != 1 ) )
756 if( pos1 != wxString::npos )
757 aliasEnd = wxString::npos;
760 filename.Replace( wxT(
"\\" ), wxT(
"/" ) );
764 if( aliasEnd == aFileName.length() -1 )
767 if( aliasEnd != wxString::npos )
770 if( aliasEnd == aliasStart )
773 lpath = filename.substr( aliasStart, aliasEnd );
776 if( wxString::npos != lpath.find_first_of( wxT(
"{}[]()%~<>\"='`;:.,&?/\\|$" ) ) )
780 lpath = aFileName.substr( aliasEnd + 1 );
788 aliasEnd = wxString::npos;
790 if( aFileName.StartsWith( wxS(
"${" ) ) )
791 aliasEnd = aFileName.find(
'}' );
792 else if( aFileName.StartsWith( wxS(
"$(" ) ) )
793 aliasEnd = aFileName.find(
')' );
795 if( aliasEnd != wxString::npos )
796 lpath = aFileName.substr( aliasEnd + 1 );
804 wxString lpath_no_sep = lpath;
807 lpath_no_sep.Replace(
"/",
" " );
808 lpath_no_sep.Replace(
"\\",
" " );
811 if( lpath_no_sep.Length() > 1 && lpath_no_sep[1] ==
':' )
812 lpath_no_sep[1] =
' ';
815 if( wxString::npos != lpath_no_sep.find_first_of( wxFileName::GetForbiddenChars() ) )
829 bool hasKisys3D =
false;
840 if( mS->first == wxS(
"KICAD_PTEMPLATES" )
841 || mS->first.Matches( wxS(
"KICAD*_FOOTPRINT_DIR") ) )
847 if( wxString::npos != mS->second.GetValue().find( wxS(
"://" ) ) )
854 paths.push_back( mS->first );
856 if( mS->first.Matches( wxS(
"KICAD*_3DMODEL_DIR") ) )
wxFileName GetTemporaryFileName(const wxString &aName) const
bool ValidateFileName(const wxString &aFileName, bool &hasAlias) const
Return true if the given path is a valid aliased relative path.
bool createPathList(void)
Build the path list using available information such as KICAD7_3DMODEL_DIR and the 3d_path_list confi...
bool addPath(const SEARCH_PATH &aPath)
Check that a path is valid and adds it to the search list.
wxString GetProjectDir() const
bool GetKicadPaths(std::list< wxString > &paths) const
Return a list of path environment variables local to KiCad.
bool Set3DConfigDir(const wxString &aConfigDir)
Set the user's configuration directory for 3D models.
void checkEnvVarPath(const wxString &aPath)
Check the ${ENV_VAR} component of a path and adds it to the resolver's path list if it is not yet in ...
std::list< SEARCH_PATH > m_paths
List of base paths to search from.
bool SetProject(PROJECT *aProject, bool *flgChanged=nullptr)
Set the current KiCad project directory as the first entry in the model path list.
void SetProgramBase(PGM_BASE *aBase)
Set a pointer to the application's PGM_BASE instance used to extract the local env vars.
bool SplitAlias(const wxString &aFileName, wxString &anAlias, wxString &aRelPath) const
Return true if the given name contains an alias and populates the string anAlias with the alias and a...
wxString ResolvePath(const wxString &aFileName, const wxString &aWorkingPath, const EMBEDDED_FILES *aFiles)
Determine the full path of the given file name.
wxString m_configDir
3D configuration directory.
const std::list< SEARCH_PATH > * GetPaths() const
Return a pointer to the internal path list; the items in:load.
bool UpdatePathList(const std::vector< SEARCH_PATH > &aPathList)
Clear the current path list and substitutes the given path list and update the path configuration fil...
wxString ShortenPath(const wxString &aFullPathName)
Produce a relative path based on the existing search directories or returns the same path if the path...
Container for data for KiCad programs.
virtual ENV_VAR_MAP & GetLocalEnvVariables() const
Container for project specific data.
virtual const wxString GetProjectPath() const
Return the full path of the project.
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
This file is part of the common library.
Functions related to environment variables, including help functions.
static std::mutex mutex_resolver
static const std::string KiCadUriPrefix
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
std::map< wxString, ENV_VAR_ITEM >::const_iterator ENV_VAR_MAP_CITER
KICOMMON_API wxString GetVersionedEnvVarName(const wxString &aBaseName)
Construct a versioned environment variable based on this KiCad major version.
wxString m_Pathvar
Base path as stored in the configuration file.
wxString m_Pathexp
Expanded base path.
wxString m_Alias
Alias to the base path.
wxLogTrace helper definitions.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().