OSDN Git Service

PATCH: [ 1522037 ] Add read-only option for paths in Project file
[winmerge-jp/winmerge-jp.git] / Src / ProjectFile.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 //    License (GPLv2+):
3 //    This program is free software; you can redistribute it and/or modify
4 //    it under the terms of the GNU General Public License as published by
5 //    the Free Software Foundation; either version 2 of the License, or (at
6 //    your option) any later version.
7 //    
8 //    This program is distributed in the hope that it will be useful, but
9 //    WITHOUT ANY WARRANTY; without even the implied warranty of
10 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 //    GNU General Public License for more details.
12 //
13 //    You should have received a copy of the GNU General Public License
14 //    along with this program; if not, write to the Free Software
15 //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 /////////////////////////////////////////////////////////////////////////////
17 /** 
18  * @file  ProjectFile.cpp
19  *
20  * @brief Implementation file for ProjectFile class
21  */
22 // RCS ID line follows -- this is updated by CVS
23 // $Id$
24
25 #include "stdafx.h"
26 #include "ProjectFile.h"
27 #include "XmlDoc.h"
28
29
30 /** 
31  * @brief Standard constructor.
32  */
33  ProjectFile::ProjectFile()
34 : m_subfolders(-1)
35 , m_bLeftReadOnly(FALSE)
36 , m_bRightReadOnly(FALSE)
37 {
38 }
39
40 /** 
41  * @brief Get message from exception into sError, or else throw it.
42  *
43  * If this successfully extracts the error description into the string, it simply returns FALSE
44  * If it fails to extract the error description, it rethrows the exception
45  */
46 static BOOL NTAPI False(CException *e, CString *sError)
47 {
48         if (sError == NULL)
49                 throw e;
50         TCHAR szError[1024];
51         e->GetErrorMessage(szError, 1024);
52         *sError = szError;
53         e->Delete();
54         return FALSE;
55 }
56
57 /** 
58  * @brief Open given path-file and read data from it to member variables.
59  * @param [in] path Path to project file.
60  * @param [out] sError Error string if error happened.
61  * @return TRUE if reading succeeded, FALSE if error happened.
62  */
63 BOOL ProjectFile::Read(LPCTSTR path, CString *sError)
64 {
65         return Serialize(false, path, sError);
66 }
67
68 /** 
69  * @brief Save data from member variables to path-file.
70  * @param [in] path Path to project file.
71  * @param [out] sError Error string if error happened.
72  * @return TRUE if saving succeeded, FALSE if error happened.
73  * @note paths are converted to UTF-8
74  */
75 BOOL ProjectFile::Save(LPCTSTR path, CString *sError)
76 {
77         return Serialize(true, path, sError);
78 }
79
80         
81 /** 
82  * @brief Read or write project file
83  * @param [in] writing TRUE if project file is saved, FALSE if it is loaded.
84  * @param [in] path Path to project file.
85  * @param [out] sError Error string if error happened.
86  * @return TRUE if operation succeeded, FALSE if error happened.
87  */
88 BOOL ProjectFile::Serialize(bool writing, LPCTSTR path, CString *sError)
89 {
90         int leftReadOnly = m_bLeftReadOnly ? 1 : 0;
91         int rightReadOnly = m_bRightReadOnly ? 1 : 0;
92
93         try
94         {
95                 XmlDoc::XML_LOADSAVE loadSave = (writing ? XmlDoc::XML_SAVE : XmlDoc::XML_LOAD);
96
97                 XmlDoc doc(path, loadSave, _T("UTF-8"));
98                 doc.Begin();
99                 {
100                         XmlElement project(doc, _T("project"));
101                         {
102                                 XmlElement paths(doc, _T("paths"));
103                                 {
104                                         XmlElement(doc, _T("left"), m_leftFile);
105                                 } {
106                                         XmlElement(doc, _T("left-readonly"), leftReadOnly);
107                                 } {
108                                         XmlElement(doc, _T("right"), m_rightFile);
109                                 } {
110                                         XmlElement(doc, _T("right-readonly"), rightReadOnly);
111                                 } {
112                                         XmlElement(doc, _T("filter"), m_filter);
113                                 } {
114                                         XmlElement(doc, _T("subfolders"), m_subfolders);
115                                 }
116                         }
117                 }
118                 doc.End();
119
120         }
121         catch (CException *e)
122         {
123                 return False(e, sError);
124         }
125
126         if (!writing)
127         {
128                 m_bLeftReadOnly = (leftReadOnly == 1);
129                 m_bRightReadOnly = (rightReadOnly == 1);
130         }
131         return TRUE;
132 }
133
134 /** 
135  * @brief Returns if left path is defined.
136  */
137 BOOL ProjectFile::HasLeft() const
138 {
139         return !m_leftFile.IsEmpty();
140 }
141
142 /** 
143  * @brief Returns if right path is defined.
144  */
145 BOOL ProjectFile::HasRight() const
146 {
147         return !m_rightFile.IsEmpty();
148 }
149
150 /** 
151  * @brief Returns if filter is defined.
152  */
153 BOOL ProjectFile::HasFilter() const
154 {
155         return !m_filter.IsEmpty();
156 }
157
158 /** 
159  * @brief Returns if subfolder is included.
160  */
161 BOOL ProjectFile::HasSubfolders() const
162 {
163         return (m_subfolders != -1);
164 }
165
166 /** 
167  * @brief Returns left path.
168  * @param [out] pReadOnly TRUE if readonly was specified for path.
169  */
170 CString ProjectFile::GetLeft(BOOL * pReadOnly /*=NULL*/) const
171 {
172         if (pReadOnly)
173                 *pReadOnly = m_bLeftReadOnly;
174         return m_leftFile;
175 }
176
177 /** 
178  * @brief Returns if left path is specified read-only.
179  */
180 BOOL ProjectFile::GetLeftReadOnly() const
181 {
182         return m_bLeftReadOnly;
183 }
184
185 /** 
186  * @brief Set left path, returns old left path.
187  * @param [in] sLeft Left path.
188  * @param [in] bReadOnly Will path be recorded read-only?
189  */
190 CString ProjectFile::SetLeft(const CString& sLeft, const BOOL * pReadOnly /*=NULL*/)
191 {
192         CString sLeftOld = GetLeft();
193         m_leftFile = sLeft;
194         if (pReadOnly)
195                 m_bLeftReadOnly = *pReadOnly;
196
197         return sLeftOld;
198 }
199
200 /** 
201  * @brief Returns right path.
202  * @param [out] pReadOnly TRUE if readonly was specified for path.
203  */
204 CString ProjectFile::GetRight(BOOL * pReadOnly /*=NULL*/) const
205 {
206         if (pReadOnly)
207                 *pReadOnly = m_bRightReadOnly;
208         return m_rightFile;
209 }
210
211 /** 
212  * @brief Returns if right path is specified read-only.
213  */
214 BOOL ProjectFile::GetRightReadOnly() const
215 {
216         return m_bRightReadOnly;
217 }
218
219 /** 
220  * @brief Set right path, returns old right path.
221  * @param [in] sRight Right path.
222  * @param [in] bReadOnly Will path be recorded read-only?
223  */
224 CString ProjectFile::SetRight(const CString& sRight, const BOOL * pReadOnly /*=NULL*/)
225 {
226         CString sRightOld = GetRight();
227         m_rightFile = sRight;
228         if (pReadOnly)
229                 m_bRightReadOnly = *pReadOnly;
230
231         return sRightOld;
232 }
233
234 /** 
235  * @brief Returns filter.
236  */
237 CString ProjectFile::GetFilter() const
238 {
239         return m_filter;
240 }
241
242 /** 
243  * @brief Set filter, returns old filter.
244  */
245 CString ProjectFile::SetFilter(const CString& sFilter)
246 {
247         CString sFilterOld = GetFilter();
248         m_filter = sFilter;
249
250         return sFilterOld;
251 }
252
253 /** 
254  * @brief Returns subfolder included -setting.
255  */
256 int ProjectFile::GetSubfolders() const
257 {
258         return m_subfolders;
259 }
260
261 /** 
262  * @brief set subfolder, returns old subfolder value.
263  */
264 int ProjectFile::SetSubfolders(const int iSubfolder)
265 {
266         int iSubfoldersOld = GetSubfolders(); 
267         m_subfolders = iSubfolder ? 1 : 0;
268
269         return iSubfoldersOld;
270 }
271
272 /** 
273  * @brief Reads one value from XML data.
274  */
275 BOOL ProjectFile::GetVal(TCHAR *pPaths, TCHAR *pVal, CString * sval,
276                 TCHAR *ptag1, TCHAR *ptag2, TCHAR *pbuf)
277 {
278         if (pPaths && pVal && pVal > pPaths)
279         {
280                 TCHAR tmpPath[MAX_PATH] = {0};
281                 TCHAR *pTagEnd = _tcsstr(pbuf, ptag2);
282                 if ((pTagEnd - pVal) < (MAX_PATH * sizeof(TCHAR)))
283                 {
284                         pVal += _tcslen(ptag1);
285                         _tcsncpy(tmpPath, pVal, pTagEnd - pVal);
286                         *sval = tmpPath;
287                         return TRUE;
288                 }
289         }
290         return FALSE;
291 }
292
293 /** 
294  * @brief Returns left and right paths and recursive from project file
295  * 
296  * @param [out] sLeft Left path
297  * @param [out] sRight Right path
298  * @param [out] bSubFolders If TRUE subfolders included (recursive compare)
299  */
300 void ProjectFile::GetPaths(CString & sLeft, CString & sRight,
301         BOOL & bSubfolders) const
302 {
303         if (HasLeft())
304                 sLeft = GetLeft();
305         if (HasRight())
306                 sRight = GetRight();
307         if (HasSubfolders())
308                 bSubfolders = (GetSubfolders() == 1);
309 }