OSDN Git Service

[ 739529 ] project file & directory filters
[winmerge-jp/winmerge-jp.git] / Src / FileFilterMgr.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // FileFilterMgr.cpp : implementation file
3 // see FileFilterMgr.h for description
4 /////////////////////////////////////////////////////////////////////////////
5 //    License (GPLv2+):
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 /////////////////////////////////////////////////////////////////////////////
10 //
11
12 #include "stdafx.h"
13 #include "FileFilterMgr.h"
14 #include "RegExp.h"
15
16 #ifdef _DEBUG
17 #define new DEBUG_NEW
18 #undef THIS_FILE
19 static char THIS_FILE[] = __FILE__;
20 #endif
21
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
24 // Perry, 2003-05-18
25
26 typedef CTypedPtrList<CPtrList, CRegExp*>RegList;
27 static void DeleteRegList(RegList & reglist)
28 {
29         while (!reglist.IsEmpty())
30         {
31                 CRegExp * regexp = reglist.RemoveHead();
32                 delete regexp;
33         }
34 }
35 // One actual filter
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
38 struct FileFilter
39 {
40         bool default_include;
41         CString name;
42         CString fullpath;
43         RegList filefilters; 
44         RegList dirfilters; 
45         FileFilter() : default_include(true) { }
46         ~FileFilter();
47 };
48 FileFilter::~FileFilter()
49 {
50         DeleteRegList(filefilters);
51         DeleteRegList(dirfilters);
52 }
53
54 FileFilterMgr::~FileFilterMgr()
55 {
56         DeleteAllFilters();
57 }
58
59 // Load 
60 void FileFilterMgr::LoadFromDirectory(LPCTSTR szPattern)
61 {
62         DeleteAllFilters();
63         CFileFind finder;
64    BOOL bWorking = finder.FindFile(szPattern);
65    while (bWorking)
66    {
67       bWorking = finder.FindNextFile();
68                 if (finder.IsDots() || finder.IsDirectory())
69                         continue;
70                 LoadFilterFile(finder.GetFilePath(), finder.GetFileName());
71    }
72 }
73
74 void FileFilterMgr::DeleteAllFilters()
75 {
76         for (int i=0; i<m_filters.GetSize(); ++i)
77         {
78                 delete m_filters[i];
79                 m_filters[i] = 0;
80         }
81         m_filters.RemoveAll();
82 }
83
84 // Add a single pattern (if nonempty & valid) to a pattern list
85 static void AddFilterPattern(RegList & reglist, CString & str)
86 {
87         str.TrimLeft();
88         str.MakeUpper();
89         if (str.IsEmpty()) return;
90         CRegExp * regexp = new CRegExp;
91         if (regexp->RegComp(str))
92                 reglist.AddTail(regexp);
93         else
94                 delete regexp;
95 }
96
97 // Parse a filter file, and add it to array if valid
98 void FileFilterMgr::LoadFilterFile(LPCTSTR szFilepath, LPCTSTR szFilename)
99 {
100         CStdioFile file;
101         if (!file.Open(szFilepath, CFile::modeRead))
102                 return;
103         FileFilter *pfilter = new FileFilter;
104         pfilter->fullpath = szFilepath;
105         pfilter->name = szFilename; // default if no name
106         CString sLine;
107         while (file.ReadString(sLine))
108         {
109                 if (0 == _tcsncmp(sLine, _T("name:"), 5))
110                 {
111                         // specifies display name
112                         CString str = sLine.Mid(5);
113                         str.TrimLeft();
114                         if (!str.IsEmpty())
115                                 pfilter->name = str;
116                 }
117                 else if (0 == _tcsncmp(sLine, _T("def:"), 4))
118                 {
119                         // specifies default
120                         CString str = sLine.Mid(4);
121                         str.TrimLeft();
122                         if (str == _T("0") || str == _T("no") || str == _T("exclude"))
123                                 pfilter->default_include = false;
124                         else if (str == _T("1") || str == _T("yes") || str == _T("include"))
125                                 pfilter->default_include = true;
126                 }
127                 else if (0 == _tcsncmp(sLine, _T("f:"), 2))
128                 {
129                         // file filter
130                         CString str = sLine.Mid(2);
131                         AddFilterPattern(pfilter->filefilters, str);
132                 }
133                 else if (0 == _tcsncmp(sLine, _T("d:"), 2))
134                 {
135                         // directory filter
136                         CString str = sLine.Mid(2);
137                         AddFilterPattern(pfilter->dirfilters, str);
138                 }
139         }
140         m_filters.Add(pfilter);
141 }
142
143 // Give client back a pointer to the actual filter
144 // We just do a linear search, because this is seldom called
145 FileFilter * FileFilterMgr::GetFilter(LPCTSTR szFilterName)
146 {
147         for (int i=0; i<m_filters.GetSize(); ++i)
148         {
149                 if (m_filters[i]->name == szFilterName)
150                         return m_filters[i];
151         }
152         return 0;
153 }
154
155 // return TRUE if string passes
156 BOOL TestAgainstRegList(const RegList & reglist, LPCTSTR szTest)
157 {
158         CString str = szTest;
159         str.MakeUpper();
160         for (POSITION pos = reglist.GetHeadPosition(); pos; )
161         {
162                 CRegExp * regexp = reglist.GetNext(pos);
163                 if (regexp->RegFind(str) != -1)
164                         return TRUE;
165         }
166         return FALSE;
167 }
168
169 // return TRUE if file passes the filter
170 BOOL FileFilterMgr::TestFileNameAgainstFilter(FileFilter * pFilter, LPCTSTR szFileName)
171 {
172         if (!pFilter) return TRUE;
173         if (TestAgainstRegList(pFilter->filefilters, szFileName))
174                 return !pFilter->default_include;
175         return pFilter->default_include;
176 }
177
178 // return TRUE if directory passes the filter
179 BOOL FileFilterMgr::TestDirNameAgainstFilter(FileFilter * pFilter, LPCTSTR szDirName)
180 {
181         if (!pFilter) return TRUE;
182         if (TestAgainstRegList(pFilter->dirfilters, szDirName))
183                 return !pFilter->default_include;
184         return pFilter->default_include;
185 }
186
187 CString FileFilterMgr::GetFilterName(int i)
188 {
189         return m_filters[i]->name; 
190 }