1 /////////////////////////////////////////////////////////////////////////////
2 // FileFilterMgr.cpp : implementation file
3 // see FileFilterMgr.h for description
4 /////////////////////////////////////////////////////////////////////////////
6 // This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
7 // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8 // You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
9 /////////////////////////////////////////////////////////////////////////////
11 * @file FileFilterMgr.cpp
13 * @brief Implementation of FileFilterMgr and supporting routines
15 // RCS ID line follows -- this is updated by CVS
19 #include "FileFilterMgr.h"
25 static char THIS_FILE[] = __FILE__;
28 void DeleteRegList(RegList & reglist)
30 while (!reglist.IsEmpty())
32 CRegExp * regexp = reglist.RemoveHead();
38 * @brief One actual filter.
40 * For example, this might be a GNU C filter, excluding *.o files and CVS
41 * directories. That is to say, a filter is a set of file masks and
52 FileFilter() : default_include(true) { }
55 FileFilter::~FileFilter()
57 DeleteRegList(filefilters);
58 DeleteRegList(dirfilters);
61 FileFilterMgr::~FileFilterMgr()
67 * @brief Load filter file from disk.
69 * @param [in] szPattern Pattern from where to load filters, for example "\\Filters\\*.flt"
70 * @param [in] szExt File-extension of filter files
72 void FileFilterMgr::LoadFromDirectory(LPCTSTR szPattern, LPCTSTR szExt)
74 // DeleteAllFilters();
76 BOOL bWorking = finder.FindFile(szPattern);
77 int extlen = szExt ? _tcslen(szExt) : 0;
80 bWorking = finder.FindNextFile();
81 if (finder.IsDots() || finder.IsDirectory())
83 CString sFilename = finder.GetFileName();
86 // caller specified a specific extension
87 // (This is really a workaround for brokenness in windows, which
88 // doesn't screen correctly on extension in pattern)
89 if (sFilename.Right(extlen).CompareNoCase(szExt))
92 FileFilter * pfilter = LoadFilterFile(finder.GetFilePath(), sFilename);
93 m_filters.Add(pfilter);
98 * @brief Removes all filters from current list.
100 void FileFilterMgr::DeleteAllFilters()
102 for (int i=0; i<m_filters.GetSize(); ++i)
107 m_filters.RemoveAll();
111 * @brief Add a single pattern (if nonempty & valid) to a pattern list.
113 * @param [in] RegList List where pattern is added.
114 * @param [in] str Temporary variable (ie, it may be altered)
116 static void AddFilterPattern(RegList & reglist, CString & str)
118 LPCTSTR commentLeader = _T("##"); // Starts comment
122 // Ignore lines beginning with '##'
123 int pos = str.Find(commentLeader);
127 // Find possible comment-separator '<whitespace>##'
128 while (pos > 0 && !_istspace(str[pos - 1]))
129 pos = str.Find(commentLeader, pos);
131 // Remove comment and whitespaces before it
138 CRegExp * regexp = new CRegExp;
139 if (regexp->RegComp(str))
140 reglist.AddTail(regexp);
146 * @brief Parse a filter file, and add it to array if valid.
148 * @param [in] szFilePath Path (w/o filename) to file to load.
149 * @param [in] szFilename Name of file to load.
151 FileFilter * FileFilterMgr::LoadFilterFile(LPCTSTR szFilepath, LPCTSTR szFilename)
154 if (!file.Open(szFilepath, CFile::modeRead | CFile::shareDenyNone))
156 FileFilter *pfilter = new FileFilter;
157 pfilter->fullpath = szFilepath;
158 pfilter->name = szFilename; // default if no name
160 while (file.ReadString(sLine))
165 if (0 == _tcsncmp(sLine, _T("name:"), 5))
167 // specifies display name
168 CString str = sLine.Mid(5);
173 else if (0 == _tcsncmp(sLine, _T("desc:"), 5))
175 // specifies display name
176 CString str = sLine.Mid(5);
179 pfilter->description = str;
181 else if (0 == _tcsncmp(sLine, _T("def:"), 4))
184 CString str = sLine.Mid(4);
186 if (str == _T("0") || str == _T("no") || str == _T("exclude"))
187 pfilter->default_include = false;
188 else if (str == _T("1") || str == _T("yes") || str == _T("include"))
189 pfilter->default_include = true;
191 else if (0 == _tcsncmp(sLine, _T("f:"), 2))
194 CString str = sLine.Mid(2);
195 AddFilterPattern(pfilter->filefilters, str);
197 else if (0 == _tcsncmp(sLine, _T("d:"), 2))
200 CString str = sLine.Mid(2);
201 AddFilterPattern(pfilter->dirfilters, str);
208 * @brief Give client back a pointer to the actual filter.
210 * @param [in] szFilterPath Full path to filterfile.
211 * @return Pointer to found filefilter or NULL;
212 * @note We just do a linear search, because this is seldom called
214 FileFilter * FileFilterMgr::GetFilterByPath(LPCTSTR szFilterPath)
216 for (int i=0; i<m_filters.GetSize(); ++i)
218 if (m_filters[i]->fullpath == szFilterPath)
225 * @brief Test given string against given regexp list.
227 * @param [in] reglist List of regexps to test against.
228 * @param [in] szTest String to test against regexps.
229 * @return TRUE if string passes
231 BOOL TestAgainstRegList(const RegList & reglist, LPCTSTR szTest)
233 CString str = szTest;
235 for (POSITION pos = reglist.GetHeadPosition(); pos; )
237 CRegExp * regexp = reglist.GetNext(pos);
238 if (regexp->RegFind(str) != -1)
245 * @brief Test given filename against filefilter.
247 * Test filename against active filefilter. If matching rule is found
248 * we must first determine type of rule that matched. If we return FALSE
249 * from this function directory scan marks file as skipped.
251 * @param [in] pFilter Pointer to filefilter
252 * @param [in] szFileName Filename to test
253 * @return TRUE if file passes the filter
255 BOOL FileFilterMgr::TestFileNameAgainstFilter(FileFilter * pFilter, LPCTSTR szFileName)
257 if (!pFilter) return TRUE;
258 if (TestAgainstRegList(pFilter->filefilters, szFileName))
259 return !pFilter->default_include;
260 return pFilter->default_include;
264 * @brief Test given directory name against filefilter.
266 * Test directory name against active filefilter. If matching rule is found
267 * we must first determine type of rule that matched. If we return FALSE
268 * from this function directory scan marks file as skipped.
270 * @param [in] pFilter Pointer to filefilter
271 * @param [in] szDirName Directory name to test
272 * @return TRUE if directory name passes the filter
274 BOOL FileFilterMgr::TestDirNameAgainstFilter(FileFilter * pFilter, LPCTSTR szDirName)
276 if (!pFilter) return TRUE;
277 if (TestAgainstRegList(pFilter->dirfilters, szDirName))
278 return !pFilter->default_include;
279 return pFilter->default_include;
283 * @brief Return name of filter.
285 * @param [in] i Index of filter.
286 * @return Name of filter in given index.
288 CString FileFilterMgr::GetFilterName(int i) const
290 return m_filters[i]->name;
294 * @brief Return description of filter.
296 * @param [in] i Index of filter.
297 * @return Description of filter in given index.
299 CString FileFilterMgr::GetFilterDesc(int i) const
301 return m_filters[i]->description;
305 * @brief Return full path to filter.
307 * @param [in] i Index of filter.
308 * @return Full path of filter in given index.
310 CString FileFilterMgr::GetFilterPath(int i) const
312 return m_filters[i]->fullpath;
316 * @brief Return full path to filter.
318 * @param [in] pFilter Pointer to filter.
319 * @return Full path of filter.
321 CString FileFilterMgr::GetFullpath(FileFilter * pfilter) const
323 return pfilter->fullpath;
327 * @brief Reload filter from disk
329 * Reloads filter from disk. This is done by creating a new one
330 * to substitute for old one.
331 * @param [in] pFilter Pointer to filter to reload.
333 void FileFilterMgr::ReloadFilterFromDisk(FileFilter * pfilter)
335 FileFilter * newfilter = LoadFilterFile(pfilter->fullpath, pfilter->name);
336 for (int i=0; i<m_filters.GetSize(); ++i)
338 if (pfilter == m_filters[i])
340 m_filters.RemoveAt(i);
345 m_filters.Add(newfilter);
349 * @brief Reload filter from disk
351 * Reloads filter from disk. This is done by creating a new one
352 * to substitute for old one.
353 * @param [in] szFullPath Full path to filter file to reload.
355 void FileFilterMgr::ReloadFilterFromDisk(LPCTSTR szFullPath)
357 FileFilter * filter = GetFilterByPath(szFullPath);
358 ReloadFilterFromDisk(filter);