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() )
247 std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack )
251 if( aFileName.empty() )
252 return wxEmptyString;
258 wxString tname = aFileName;
262 tname.Replace(
"\\",
"/" );
274 if( aEmbeddedFilesStack.empty() )
276 wxLogTrace( wxT(
"KICAD_EMBED" ),
277 wxT(
"No EMBEDDED_FILES object provided for kicad_embed URI" ) );
278 return wxEmptyString;
283 wxFileName temp_file = aEmbeddedFilesStack[0]->GetTemporaryFileName(
path );
286 while( !temp_file.IsOk() && ii < (
int) aEmbeddedFilesStack.size() )
287 temp_file = aEmbeddedFilesStack[ii++]->GetTemporaryFileName(
path );
289 if( !temp_file.IsOk() )
291 wxLogTrace( wxT(
"KICAD_EMBED" ),
292 wxT(
"Failed to get temp file '%s' for kicad_embed URI" ),
path );
293 return wxEmptyString;
296 wxLogTrace( wxT(
"KICAD_EMBED" ), wxT(
"Opening embedded file '%s' as '%s'" ),
297 tname, temp_file.GetFullPath() );
299 return temp_file.GetFullPath();
302 wxFileName tmpFN( tname );
306 if( tmpFN.FileExists() )
309 tname = tmpFN.GetFullPath();
313 if( aFileName.StartsWith( wxS(
"${" ) ) || aFileName.StartsWith( wxS(
"$(" ) ) )
321 if( aFileName.StartsWith(
"${" ) || aFileName.StartsWith(
"$(" ) )
326 wxString errmsg =
"[3D File Resolver] No such path; ensure the environment var is "
328 errmsg.append(
"\n" );
329 errmsg.append( tname );
330 errmsg.append(
"\n" );
334 return wxEmptyString;
346 if( !
m_paths.begin()->m_Pathexp.empty() && !tname.StartsWith(
":" ) )
348 tmpFN.Assign(
m_paths.begin()->m_Pathexp,
"" );
349 wxString fullPath = tmpFN.GetPathWithSep() + tname;
353 if( wxFileName::FileExists( fullPath ) )
355 tmpFN.Assign( fullPath );
357 tname = tmpFN.GetFullPath();
364 if( !aWorkingPath.IsEmpty() && !tname.StartsWith(
":" ) )
366 wxString tmp = aWorkingPath;
367 tmp.Append( tmpFN.GetPathSeparator() );
371 if( tmpFN.MakeAbsolute() && tmpFN.FileExists() )
373 tname = tmpFN.GetFullPath();
379 if( !tname.StartsWith( wxS(
":" ) ) )
382 wxString fullPath( wxString::Format( wxS(
"${%s}" ),
384 fullPath.Append( fpath.GetPathSeparator() );
385 fullPath.Append( tname );
387 fpath.Assign( fullPath );
391 tname = fpath.GetFullPath();
408 wxString errmsg =
"[3D File Resolver] No such path";
409 errmsg.append( wxS(
"\n" ) );
410 errmsg.append( tname );
411 errmsg.append( wxS(
"\n" ) );
415 return wxEmptyString;
421 if(
path.m_Alias.StartsWith( wxS(
"${" ) ) ||
path.m_Alias.StartsWith( wxS(
"$(" ) ) )
424 if(
path.m_Alias == alias && !
path.m_Pathexp.empty() )
426 wxFileName fpath( wxFileName::DirName(
path.m_Pathexp ) );
427 wxString fullPath = fpath.GetPathWithSep() + relpath;
431 if( wxFileName::FileExists( fullPath ) )
435 wxFileName tmp( fullPath );
438 tname = tmp.GetFullPath();
448 wxString errmsg =
"[3D File Resolver] No such path; ensure the path alias is defined";
449 errmsg.append(
"\n" );
450 errmsg.append( tname.substr( 1 ) );
451 errmsg.append(
"\n" );
455 return wxEmptyString;
469 while( tpath.
m_Pathvar.EndsWith( wxT(
"\\" ) ) )
480 if( !
path.DirExists() )
482 wxString versionedPath = wxString::Format( wxS(
"${%s}" ),
487 || aPath.
m_Pathvar == wxS(
"${KISYS3DMOD}" )
488 || aPath.
m_Pathvar == wxS(
"$(KISYS3DMOD)" ) )
494 wxString msg =
_(
"The given path does not exist" );
495 msg.append( wxT(
"\n" ) );
507 while( tpath.
m_Pathexp.EndsWith( wxT(
"\\" ) ) )
515 std::list< SEARCH_PATH >::iterator sPL =
m_paths.begin();
516 std::list< SEARCH_PATH >::iterator ePL =
m_paths.end();
520 if( tpath.
m_Alias == sPL->m_Alias )
522 wxString msg =
_(
"Alias: " );
524 msg.append( wxT(
"\n" ) );
525 msg.append(
_(
"This path:" ) + wxS(
" " ) );
527 msg.append( wxT(
"\n" ) );
528 msg.append(
_(
"Existing path:" ) + wxS(
" " ) );
529 msg.append( sPL->m_Pathvar );
544 bool useParen =
false;
546 if( aPath.StartsWith( wxS(
"$(" ) ) )
548 else if( !aPath.StartsWith( wxS(
"${" ) ) )
554 pEnd = aPath.find( wxS(
")" ) );
556 pEnd = aPath.find( wxS(
"}" ) );
558 if( pEnd == wxString::npos )
561 wxString envar = aPath.substr( 0, pEnd + 1 );
570 if( sPL->m_Alias == envar )
573 if( !sPL->m_Alias.StartsWith( wxS(
"${" ) ) )
584 wxUniChar psep = tmpFN.GetPathSeparator();
587 if( !tmpFN.DirExists() )
604 wxString fname = aFullPathName;
611 std::list< SEARCH_PATH >::const_iterator sL =
m_paths.begin();
618 if( sL->m_Pathexp.empty() )
627 if( sL->m_Alias.StartsWith( wxS(
"${" ) ) || sL->m_Alias.StartsWith( wxS(
"$(" ) ) )
637 fpath.Assign( tpath, wxT(
"" ) );
641 fpath.Assign( sL->m_Pathexp, wxT(
"" ) );
644 wxString fps = fpath.GetPathWithSep();
647 idx = fname.find( fps );
651 fname = fname.substr( fps.size() );
655 fname.Replace( wxT(
"\\" ), wxT(
"/" ) );
658 if( sL->m_Alias.StartsWith( wxS(
"${" ) ) || sL->m_Alias.StartsWith( wxS(
"$(" ) ) )
662 tname.Append( wxS(
"/" ) );
663 tname.append( fname );
669 tname.append( sL->m_Alias );
670 tname.append( wxS(
"}/" ) );
671 tname.append( fname );
685 fname.Replace( wxT(
"\\" ), wxT(
"/" ) );
699 wxString& anAlias, wxString& aRelPath )
const
704 size_t searchStart = 0;
706 if( aFileName.StartsWith( wxT(
":" ) ) )
709 size_t tagpos = aFileName.find( wxT(
":" ), searchStart );
711 if( tagpos == wxString::npos || tagpos == searchStart )
714 if( tagpos + 1 >= aFileName.length() )
717 anAlias = aFileName.substr( searchStart, tagpos - searchStart );
718 aRelPath = aFileName.substr( tagpos + 1 );
735 if( aFileName.empty() )
738 if( aFileName.StartsWith( wxT(
"file://" ) )
741 size_t prefixLength = aFileName.StartsWith( wxT(
"file://" ) ) ? 7 : 14;
742 if( aFileName.length() > prefixLength && aFileName[prefixLength] !=
'/' )
748 wxString filename = aFileName;
750 size_t aliasStart = aFileName.StartsWith(
':' ) ? 1 : 0;
751 size_t aliasEnd = aFileName.find(
':', aliasStart );
755 filename.Replace( wxT(
"/" ), wxT(
"\\" ) );
758 if( aliasEnd != wxString::npos )
760 size_t pos1 = filename.find( wxT(
":\\" ) );
762 if( pos1 != wxString::npos && ( pos1 != aliasEnd || pos1 != 1 ) )
766 if( pos1 != wxString::npos )
767 aliasEnd = wxString::npos;
770 filename.Replace( wxT(
"\\" ), wxT(
"/" ) );
774 if( aliasEnd == aFileName.length() -1 )
777 if( aliasEnd != wxString::npos )
780 if( aliasEnd == aliasStart )
783 lpath = filename.substr( aliasStart, aliasEnd );
786 if( wxString::npos != lpath.find_first_of( wxT(
"{}[]()%~<>\"='`;:.,&?/\\|$" ) ) )
790 lpath = aFileName.substr( aliasEnd + 1 );
798 aliasEnd = wxString::npos;
800 if( aFileName.StartsWith( wxS(
"${" ) ) )
801 aliasEnd = aFileName.find(
'}' );
802 else if( aFileName.StartsWith( wxS(
"$(" ) ) )
803 aliasEnd = aFileName.find(
')' );
805 if( aliasEnd != wxString::npos )
806 lpath = aFileName.substr( aliasEnd + 1 );
814 wxString lpath_no_sep = lpath;
817 lpath_no_sep.Replace(
"/",
" " );
818 lpath_no_sep.Replace(
"\\",
" " );
821 if( lpath_no_sep.Length() > 1 && lpath_no_sep[1] ==
':' )
822 lpath_no_sep[1] =
' ';
825 if( wxString::npos != lpath_no_sep.find_first_of( wxFileName::GetForbiddenChars() ) )
839 bool hasKisys3D =
false;
850 if( mS->first == wxS(
"KICAD_PTEMPLATES" )
851 || mS->first.Matches( wxS(
"KICAD*_FOOTPRINT_DIR") ) )
857 if( wxString::npos != mS->second.GetValue().find( wxS(
"://" ) ) )
864 paths.push_back( mS->first );
866 if( mS->first.Matches( wxS(
"KICAD*_3DMODEL_DIR") ) )
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...
wxString ResolvePath(const wxString &aFileName, const wxString &aWorkingPath, std::vector< const EMBEDDED_FILES * > aEmbeddedFilesStack)
Determine the full path of the given file name.
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.
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 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 SetProject(const PROJECT *aProject, bool *flgChanged=nullptr)
Set the current KiCad project directory as the first entry in the model path list.
const PROJECT * m_project
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().