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.
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().