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 /////////////////////////////////////////////////////////////////////////////
13 #include "FileFilterMgr.h"
19 static char THIS_FILE[] = __FILE__;
22 // I think that CRegExp doesn't copy correctly (I get heap corruption in CRegList::program)
23 // so I'm using pointers to avoid its copy constructor
26 typedef CTypedPtrList<CPtrList, CRegExp*>RegList;
27 static void DeleteRegList(RegList & reglist)
29 while (!reglist.IsEmpty())
31 CRegExp * regexp = reglist.RemoveHead();
36 // For example, this might be a GNU C filter, excluding *.o files and CVS directories
37 // That is to say, a filter is a set of file masks and directory masks
45 FileFilter() : default_include(true) { }
48 FileFilter::~FileFilter()
50 DeleteRegList(filefilters);
51 DeleteRegList(dirfilters);
54 FileFilterMgr::~FileFilterMgr()
60 void FileFilterMgr::LoadFromDirectory(LPCTSTR szPattern, LPCTSTR szExt)
62 // DeleteAllFilters();
64 BOOL bWorking = finder.FindFile(szPattern);
65 int extlen = szExt ? _tcslen(szExt) : 0;
68 bWorking = finder.FindNextFile();
69 if (finder.IsDots() || finder.IsDirectory())
71 CString sFilename = finder.GetFileName();
74 // caller specified a specific extension
75 // (This is really a workaround for brokenness in windows, which
76 // doesn't screen correctly on extension in pattern)
77 if (sFilename.Right(extlen).CompareNoCase(szExt))
80 FileFilter * pfilter = LoadFilterFile(finder.GetFilePath(), sFilename);
81 m_filters.Add(pfilter);
85 void FileFilterMgr::DeleteAllFilters()
87 for (int i=0; i<m_filters.GetSize(); ++i)
92 m_filters.RemoveAll();
95 // Add a single pattern (if nonempty & valid) to a pattern list
96 static void AddFilterPattern(RegList & reglist, CString & str)
100 LPCTSTR commentLeader = _T(" ##");
101 // anything from commentLeader to end of line is a comment
102 int comment = str.Find(commentLeader);
105 str = str.Left(comment);
107 if (str.IsEmpty()) return;
108 CRegExp * regexp = new CRegExp;
109 if (regexp->RegComp(str))
110 reglist.AddTail(regexp);
115 // Parse a filter file, and add it to array if valid
116 FileFilter * FileFilterMgr::LoadFilterFile(LPCTSTR szFilepath, LPCTSTR szFilename)
119 if (!file.Open(szFilepath, CFile::modeRead))
121 FileFilter *pfilter = new FileFilter;
122 pfilter->fullpath = szFilepath;
123 pfilter->name = szFilename; // default if no name
125 while (file.ReadString(sLine))
127 if (0 == _tcsncmp(sLine, _T("name:"), 5))
129 // specifies display name
130 CString str = sLine.Mid(5);
135 else if (0 == _tcsncmp(sLine, _T("def:"), 4))
138 CString str = sLine.Mid(4);
140 if (str == _T("0") || str == _T("no") || str == _T("exclude"))
141 pfilter->default_include = false;
142 else if (str == _T("1") || str == _T("yes") || str == _T("include"))
143 pfilter->default_include = true;
145 else if (0 == _tcsncmp(sLine, _T("f:"), 2))
148 CString str = sLine.Mid(2);
149 AddFilterPattern(pfilter->filefilters, str);
151 else if (0 == _tcsncmp(sLine, _T("d:"), 2))
154 CString str = sLine.Mid(2);
155 AddFilterPattern(pfilter->dirfilters, str);
161 // Give client back a pointer to the actual filter
162 // We just do a linear search, because this is seldom called
163 FileFilter * FileFilterMgr::GetFilter(LPCTSTR szFilterName)
165 for (int i=0; i<m_filters.GetSize(); ++i)
167 if (m_filters[i]->name == szFilterName)
173 // return TRUE if string passes
174 BOOL TestAgainstRegList(const RegList & reglist, LPCTSTR szTest)
176 CString str = szTest;
178 for (POSITION pos = reglist.GetHeadPosition(); pos; )
180 CRegExp * regexp = reglist.GetNext(pos);
181 if (regexp->RegFind(str) != -1)
187 // return TRUE if file passes the filter
188 BOOL FileFilterMgr::TestFileNameAgainstFilter(FileFilter * pFilter, LPCTSTR szFileName)
190 if (!pFilter) return TRUE;
191 if (TestAgainstRegList(pFilter->filefilters, szFileName))
192 return !pFilter->default_include;
193 return pFilter->default_include;
196 // return TRUE if directory passes the filter
197 BOOL FileFilterMgr::TestDirNameAgainstFilter(FileFilter * pFilter, LPCTSTR szDirName)
199 if (!pFilter) return TRUE;
200 if (TestAgainstRegList(pFilter->dirfilters, szDirName))
201 return !pFilter->default_include;
202 return pFilter->default_include;
205 CString FileFilterMgr::GetFilterName(int i)
207 return m_filters[i]->name;
210 CString FileFilterMgr::GetFullpath(FileFilter * pfilter) const
212 return pfilter->fullpath;
215 // Reload filter from disk (by creating a new one to substitute for old one)
216 void FileFilterMgr::ReloadFilterFromDisk(FileFilter * pfilter)
218 FileFilter * newfilter = LoadFilterFile(pfilter->fullpath, pfilter->name);
219 for (int i=0; i<m_filters.GetSize(); ++i)
221 if (pfilter == m_filters[i])
223 m_filters.RemoveAt(i);
228 m_filters.Add(newfilter);