we can have a look at this function in editormanager.cpp
bool EditorManager::SwapActiveHeaderSource()
{
cbEditor* ed = GetBuiltinEditor(GetActiveEditor());
if (!ed)
return false;
FileType ft = FileTypeOf(ed->GetFilename());
if (ft != ftHeader && ft != ftSource)
return false;
// because ft == ftHeader || ftSource, the extension has at least 1 character
bool extStartsWithCapital = wxIsupper(wxFileName(ed->GetFilename()).GetExt()[0]);
// create a list of search dirs
wxArrayString dirs;
cbProject* project = 0;
// if the file in question belongs to a different open project,
// then use that project instead.
// this fixes locating the file's pair in a workspace when the active file
// does not belong to the active project.
ProjectFile* opf = ed->GetProjectFile();
if (opf)
project = opf->GetParentProject();
// if we didn't get a valid project, try the active one
if (!project)
project = Manager::Get()->GetProjectManager()->GetActiveProject();
if (project)
{
// get project's include dirs
dirs = project->GetIncludeDirs();
if (opf)
{
wxString const &activeName = opf->file.GetName();
// first try to find the file among the opened files
for (int i = 0; i < GetEditorsCount(); ++i)
{
cbEditor* edit = GetBuiltinEditor(GetEditor(i));
if (!edit)
continue;
ProjectFile* pf = edit->GetProjectFile();
if (!pf)
continue;
if (pf->file.GetName() == activeName)
{
wxFileName const & fname = pf->file;
FileType ft_other = FileTypeOf(fname.GetFullName());
if ( ( ((ft == ftHeader) && (ft_other == ftSource))
|| ((ft == ftSource) && (ft_other == ftHeader)) )
&& (wxIsupper(fname.GetExt()[0]) == extStartsWithCapital) )
{
if (fname.FileExists())
{
cbEditor* newEd = Open(fname.GetFullPath());
if (newEd!=0L) // we found and were able to open it
return true; // --> RETURN
}
}
}
}
// second try to find in the project files - at the same time
// build the directory list for further searching if not
// successful now
for (int i = 0; i < project->GetFilesCount(); ++i)
{
ProjectFile* pf = project->GetFile(i);
if (!pf)
continue;
wxString dir = pf->file.GetPath(wxPATH_GET_VOLUME);
if (dirs.Index(dir) == wxNOT_FOUND)
dirs.Add(dir);
if (pf->file.GetName() == activeName)
{
wxFileName const & fname = pf->file;
FileType ft_other = FileTypeOf(fname.GetFullName());
if ( ( ((ft == ftHeader) && (ft_other == ftSource))
|| ((ft == ftSource) && (ft_other == ftHeader)) )
&& (wxIsupper(fname.GetExt()[0]) == extStartsWithCapital) )
{
if (fname.FileExists())
{
cbEditor* newEd = Open(fname.GetFullPath());
if (newEd!=0L) // we found and were able to open it
return true; // --> RETURN
}
}
}
}
}
else // no opf
{
// build the directory list for further searching if opf not available
for (int i = 0; i < project->GetFilesCount(); ++i)
{
ProjectFile* pf = project->GetFile(i);
if (!pf)
continue;
wxString dir = pf->file.GetPath(wxPATH_GET_VOLUME);
if (dirs.Index(dir) == wxNOT_FOUND)
dirs.Add(dir);
}
}
// if not found, continue building the list of directories for further searching
// get targets include dirs
for (int i = 0; i < project->GetBuildTargetsCount(); ++i)
{
ProjectBuildTarget* target = project->GetBuildTarget(i);
if (target)
{
for (unsigned int ti = 0; ti < target->GetIncludeDirs().GetCount(); ++ti)
{
// TODO (Morten#5#): target include dirs might override project include dirs, take append/prepend option into account
wxString dir = target->GetIncludeDirs()[ti];
if (dirs.Index(dir) == wxNOT_FOUND)
dirs.Add(dir);
}
}
}
} // project
wxFileName fname;
wxFileName fn(ed->GetFilename());
dirs.Insert(fn.GetPath(wxPATH_GET_VOLUME), 0); // add file's dir
for (unsigned int i = 0; i < dirs.GetCount(); ++i)
{
ProjectManager *pm = Manager::Get()->GetProjectManager();
if ( !pm )
break;
wxString dir = dirs[i]; // might contain macros -> replace them
Manager::Get()->GetMacrosManager()->ReplaceMacros(dir);
fname.Assign(dir + wxFileName::GetPathSeparator() + fn.GetFullName());
// Manager::Get()->GetLogManager()->DebugLog(F(_T("Looking for '%s', dir='%s'."), fname.GetFullPath().c_str(), dir.c_str()));
if (!fname.IsAbsolute() && project)
{
fname.Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE, project->GetBasePath());
// Manager::Get()->GetLogManager()->DebugLog(F(_T("Normalizing dir to '%s'."), fname.GetFullPath().c_str()));
}
wxString HeaderSource = pm->GetHeaderSource(fname);
if (!HeaderSource.IsEmpty())
{
fname.SetFullName(HeaderSource);
// Manager::Get()->GetLogManager()->DebugLog(F(_T("Located '%s'."), fname.GetFullPath().c_str()));
break;
}
}
if (fname.FileExists())
{
//Manager::Get()->GetLogManager()->DebugLog("ed=%s, pair=%s", ed->GetFilename().c_str(), pair.c_str());
cbEditor* newEd = Open(fname.GetFullPath());
if (newEd!=0L) // we found and were able to open it
return true; // --> RETURN;
}
// We couldn't find the file, maybe it does not exist. Ask the user if we
// should create it:
if (cbMessageBox(_("The file seems not to exist. Do you want to create it?"),
_("Error"), wxICON_QUESTION | wxYES_NO) == wxID_YES)
{
cbProject* project = Manager::Get()->GetProjectManager()->GetActiveProject();
if (project)
wxSetWorkingDirectory(project->GetBasePath());
// Create a suggestion for the new file name:
if (ft == ftHeader)
fn.SetExt(FileFilters::CPP_EXT);
else if (ft == ftSource)
fn.SetExt(FileFilters::H_EXT);
// else? Well, if the filename is not changed we could possibly
// overwrite an existing file with our suggestion.
cbEditor* newEd = New(fn.GetFullPath());
if (project)
{
if (cbMessageBox(_("Do you want to add this new file in the active project?"),
_("Add file to project"),
wxYES_NO | wxICON_QUESTION) == wxID_YES)
{
wxArrayInt targets;
if (Manager::Get()->GetProjectManager()->AddFileToProject(newEd->GetFilename(), project, targets) != 0)
{
ProjectFile* pf = project->GetFileByFilename(newEd->GetFilename(), false);
newEd->SetProjectFile(pf);
Manager::Get()->GetProjectManager()->RebuildTree();
}
}
}
// verify that the open files are still in sync
// the new file might have overwritten an existing one)
Manager::Get()->GetEditorManager()->CheckForExternallyModifiedFiles();
}
return false;
}
Having a quick look at the code, I think the issue I'm encountering is due to the fact that the directory is not being taken in to account, both the first (searching open files) and second (searching the project) seem to rely on filename only (i.e. not the relative path to the file).
Going back to my original example:
root
-- subdir1
Config.cpp
Config.h
-- subdir2
Config.cpp
Config.h
-- subdir3
Config.cpp
Config.hIf I open Config.cpp in either subdir1 or subdir2 with no other files open and hit 'swap...' Config.h in subdir1 is opened, I assume because the second search (the one through the project) is matching on 'Config.' without paying attention to the directory in which it resides.
Similarly, if I have Config.h from subdir1 open and Config.cpp from subdir3 open, if I hit 'swap..' on Config.h from subdir1, it switches to Config.cpp from subdir3 because it's matching on 'Config' (based on the first search which uses the open files).
I think for my issue the relative path must be taken into consideration.