#include "FileFilterHelper.h"
#include "RegExp.h"
#include "Coretools.h"
+#include "paths.h"
+
FileFilterHelper::FileFilterHelper()
{
- m_fileFilterMgr = NULL;
+ m_fileFilterMgr = new FileFilterMgr;
m_bUseMask = TRUE;
}
-/**
- * @brief Return filtermanager used.
- */
-FileFilterMgr * FileFilterHelper::GetManager()
+FileFilterHelper::~FileFilterHelper()
{
- return m_fileFilterMgr;
+ delete m_fileFilterMgr;
}
+
/**
- * @brief Set filtermanager used.
+ * @brief Return filtermanager used.
*/
-void FileFilterHelper::SetManager(FileFilterMgr * pFilterManager)
+FileFilterMgr * FileFilterHelper::GetManager()
{
- if (pFilterManager != NULL)
- m_fileFilterMgr = pFilterManager;
+ return m_fileFilterMgr;
}
/** @brief Store current filter (if filter manager validates the name) */
}
/**
+ * @ brief Returns true if directory exists or successfully created
+ * Tries to create multiple directories if needed
+ */
+static bool
+EnsureDirectoryExists(const CString & sPath)
+{
+ // paths_CanUse will
+ if (paths_CreateIfNeeded(sPath))
+ return true;
+ else
+ return false;
+
+}
+
+/**
* @brief Load any known file filters
* @todo Preserve filter selection? How?
*/
LoadFileFilterDirPattern(patternsLoaded, sPattern);
// Application data path in user profile directory
- if (GetAppDataPath(sPattern))
+ CString sAppPath;
+ if (GetAppDataPath(sAppPath))
{
- sPattern += _T("\\WinMerge\\Filters\\*.flt");
- LoadFileFilterDirPattern(patternsLoaded, sPattern);
+ CString sPath = sAppPath + _T("\\WinMerge\\Filters");
+ TestCandidateFilterPath(sPath);
+ LoadFileFilterDirPattern(patternsLoaded, sPath + _T("\\*.flt"));
}
+
// User profile local & roaming settings
CString sProfile;
if (GetUserProfilePath(sProfile))
{
- sPattern = sProfile + _T("\\Local Settings\\Application Data\\WinMerge\\Filters\\*.flt");
- LoadFileFilterDirPattern(patternsLoaded, sPattern);
- sPattern = sProfile + _T("\\Application Data\\WinMerge\\Filters\\*.flt");
- LoadFileFilterDirPattern(patternsLoaded, sPattern);
+ CString sPath = sProfile + _T("\\Local Settings\\Application Data\\WinMerge\\Filters");
+ TestCandidateFilterPath(sPath);
+ LoadFileFilterDirPattern(patternsLoaded, sPath + _T("\\*.flt"));
+
+ sPath = sProfile + _T("\\Application Data\\WinMerge\\Filters");
+ TestCandidateFilterPath(sPath);
+ LoadFileFilterDirPattern(patternsLoaded, sPath + _T("\\*.flt"));
+ }
+}
+
+/**
+ * @brief Store as path for new file filters, if we still need one and this path exists
+ */
+void
+FileFilterHelper::TestCandidateFilterPath(const CString & sPath)
+{
+ if (m_sNewFileFilterPath.IsEmpty())
+ {
+ if (EnsureDirectoryExists(sPath))
+ {
+ m_sNewFileFilterPath = sPath;
+ }
}
}
+
/**
* @brief Helper class for using filefilters.
*
+ * A FileFilterHelper object is the owner of any active mask, and of the file filter manager
+ * This is kind of a File Filter SuperManager, taking care of both inline filters from strings
+ * and loaded file filters (the latter handled by its internal file filter manager)
+ *
* This class is mainly for handling two ways to filter files in WinMerge:
* - File masks: *.ext lists (*.cpp *.h etc)
* - File filters: regular expression rules in separate files
{
public:
FileFilterHelper();
+ ~FileFilterHelper();
FileFilterMgr * GetManager();
- void SetManager(FileFilterMgr * pFilterManager);
- CString GetFileFilterPath() const { return m_sFileFilterPath; }
+ CString GetNewFileFilterPath() const { return m_sNewFileFilterPath; }
void SetFileFilterPath(LPCTSTR szFileFilterPath);
void EditFileFilter(LPCTSTR szFileFilterPath);
void GetFileFilters(FILEFILTER_INFOLIST * filters, CString & selected) const;
protected:
CString ParseExtensions(CString extensions);
+ void TestCandidateFilterPath(const CString & sPath);
+
private:
FileFilter * m_currentFilter; /*< Currently selected filefilter */
CString m_sFileFilterPath; /*< Path to current filter */
CString m_sMask; /*< File mask (if defined) "*.cpp *.h" etc */
BOOL m_bUseMask; /*< If TRUE file mask is used, filter otherwise */
+ CString m_sNewFileFilterPath; /*< Path where new filters should be created */
CRegExp m_rgx; /*< Compiled file mask regular expression */
};
TCHAR drive[_MAX_DRIVE] = {0};
VERIFY(title.LoadString(IDS_FILEFILTER_SAVENEW));
- path = theApp.m_globalFileFilter.GetFileFilterPath();
+ path = theApp.m_globalFileFilter.GetNewFileFilterPath();
+ if (path.GetLength() && path[path.GetLength()-1] != '\\')
+ path += '\\';
- // Drop filename and extension
- _tsplitpath(path, drive, dir, NULL, NULL);
- if (_tcslen(drive) > 0 )
- {
- path = drive;
- path += dir;
- }
- else
- {
- path = dir;
- }
tmplPath = path + FILE_FILTER_TEMPLATE;
#include "logfile.h"
#include "coretools.h"
#include "paths.h"
-#include "FileFilterMgr.h"
#include "FileFilterHelper.h"
#include "Plugins.h"
#include "DirScan.h" // for DirScan_InitializeDefaultCodepage
, m_pDiffTemplate(0)
, m_pDirTemplate(0)
, m_lang(IDR_MAINFRAME, IDR_MAINFRAME)
-, m_fileFilterMgr(0)
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
int CMergeApp::ExitInstance()
{
- delete m_fileFilterMgr;
delete m_mainThreadScripts;
return CWinApp::ExitInstance();
}
/** @brief Load any known file filters */
void CMergeApp::InitializeFileFilters()
{
- if (!m_fileFilterMgr)
- m_fileFilterMgr = new FileFilterMgr;
-
- m_globalFileFilter.SetManager(m_fileFilterMgr);
m_globalFileFilter.LoadAllFileFilters();
}
#include "languageselect.h"
#include "FileFilterHelper.h"
-class FileFilterMgr;
struct FileFilter;
class CAssureScriptsForThread;
class CMainFrame;
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
- FileFilterMgr * m_fileFilterMgr;
CAssureScriptsForThread * m_mainThreadScripts;
};
}
/**
+ * @brief Get canonical name of directory & return true, if it exists
+ */
+static bool GetDirName(const CString & sDir, CString& sName)
+{
+ // (Couldn't get info for just the directory from CFindFile)
+ WIN32_FIND_DATA ffd;
+ HANDLE h = FindFirstFile(sDir, &ffd);
+ if (h == INVALID_HANDLE_VALUE)
+ return false;
+ sName = ffd.cFileName;
+ FindClose(h);
+ return true;
+}
+
+/**
* Convert path to canonical long path (ie, with ~ short names expanded)
* Expand any environment strings
* If path does not exist, make canonical the part that does exist, and leave the rest as is
// advance to next component (or set ptr==0 to flag end)
ptr = (end ? end+1 : 0);
- // (Couldn't get info for just the directory from CFindFile)
- WIN32_FIND_DATA ffd;
- HANDLE h = FindFirstFile(sTemp, &ffd);
- if (h == INVALID_HANDLE_VALUE)
+ CString sNextName;
+ if (!GetDirName(sTemp, sNextName))
{
sLong = sTemp;
if (ptr)
return sLong;
}
sLong += '\\';
- sLong += ffd.cFileName;
- if (dst == DIRSLASH && !ptr &&
- (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ sLong += sNextName;
+ if (dst == DIRSLASH && !ptr)
{
sLong += '\\';
}
- FindClose(h);
}
return sLong;
}
+/**
+ * @brief Return true if path exists or if we successfully create it
+ * Expand any environment strings
+ * Create missing parts (as far as possible)
+ */
+bool paths_CreateIfNeeded(const CString & sPath)
+{
+ if (sPath.IsEmpty()) return false;
+
+ CString sTemp;
+ if (GetDirName(sPath, sTemp)) return true;
+
+ if (sPath.GetLength() >= _MAX_PATH) return false;
+
+ // Expand environment variables:
+ // Convert "%userprofile%\My Documents" to "C:\Documents and Settings\username\My Documents"
+ TCHAR fullPath[_MAX_PATH] = _T("");
+ if (!_tcschr(sPath, '%') || !ExpandEnvironmentStrings(sPath, fullPath, _MAX_PATH))
+ {
+ _tcscpy(fullPath, sPath);
+ }
+ // Now fullPath holds our desired path
+
+ CString sLong;
+ TCHAR *ptr = fullPath;
+ TCHAR *end = NULL;
+
+ // Skip to \ position d:\abcd or \\host\share\abcd
+ // indicated by ^ ^ ^
+ if (_tcslen(ptr) > 2)
+ end = _tcschr(fullPath+2, _T('\\'));
+ if (end && !_tcsnicmp(fullPath, _T("\\\\"),2))
+ end = _tcschr(end+1, _T('\\'));
+
+ if (!end) return false;
+
+ // check that first component exists
+ *end = 0;
+ if (!GetDirName(fullPath, sTemp))
+ return false;
+ *end = '\\';
+
+ ptr = end+1;
+
+ while (ptr)
+ {
+ end = _tcschr(ptr, '\\');
+ // zero-terminate current component
+ // (if we're at end, its already zero-terminated)
+ if (end)
+ *end = 0;
+
+ // advance to next component (or set ptr==0 to flag end)
+ ptr = (end ? end+1 : 0);
+
+ CString sNextName;
+ if (!GetDirName(fullPath, sNextName))
+ {
+ // try to create directory, and then double-check its existence
+ if (!CreateDirectory(fullPath, 0)
+ || !GetDirName(fullPath, sNextName))
+ {
+ return false;
+ }
+ }
+ // if not finished, restore directory string we're working in
+ if (ptr)
+ *end = '\\';
+ }
+ return true;
+}
+
+
/**
* @brief Return folder for temporary files.
*/
PATH_EXISTENCE paths_DoesPathExist(LPCTSTR szPath);
void paths_normalize(CString & sPath);
CString paths_GetLongPath(const CString & sPath);
+bool paths_CreateIfNeeded(const CString & sPath);
LPCTSTR paths_GetTempPath();
PATH_EXISTENCE GetPairComparability(LPCTSTR pszLeft, LPCTSTR pszRight);
CString ExpandShortcut(const CString &inFile);
+2005-03-04 Perry
+ PATCH: [ 1156253 ] Fix filter helper handling of new filters
+ BUG: [ 1153018 ] Create new filter, now cannot find it
+ Src: FileFilterHelper.cpp FileFilterHelper.h FileFiltersDlg.cpp Merge.cpp
+ Merge.h paths.cpp paths.h
+
2005-03-03 Kimmo
PATCH: [ 1155319 ] Select font for dir compare view
Src: DirView.cpp DirView.h MainFrm.cpp MainFrm.h Merge.rc OptionsDef.h