OSDN Git Service

PATCH: [ 1600000 ] Fix project file Has*() functions
[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 <scew/scew.h>
27
28 #include "ProjectFile.h"
29
30 // Constants for xml element names
31 const TCHAR Root_element_name[] = _T("project");
32 const TCHAR Paths_element_name[] = _T("paths");
33 const TCHAR Left_element_name[] = _T("left");
34 const TCHAR Right_element_name[] = _T("right");
35 const TCHAR Filter_element_name[] = _T("filter");
36 const TCHAR Subfolders_element_name[] = _T("subfolders");
37 const TCHAR Left_ro_element_name[] = _T("left-readonly");
38 const TCHAR Right_ro_element_name[] = _T("right-readonly");
39
40 /** 
41  * @brief Standard constructor.
42  */
43  ProjectFile::ProjectFile()
44 : m_bHasLeft(FALSE)
45 , m_bHasRight(FALSE)
46 , m_bHasFilter(FALSE)
47 , m_bHasSubfolders(FALSE)
48 , m_subfolders(-1)
49 , m_bLeftReadOnly(FALSE)
50 , m_bRightReadOnly(FALSE)
51 {
52 }
53
54 /** 
55  * @brief Open given path-file and read data from it to member variables.
56  * @param [in] path Path to project file.
57  * @param [out] sError Error string if error happened.
58  * @return TRUE if reading succeeded, FALSE if error happened.
59  */
60 BOOL ProjectFile::Read(LPCTSTR path, CString *sError)
61 {
62         BOOL loaded = FALSE;
63     scew_tree* tree = NULL;
64     scew_parser* parser = NULL;
65
66     parser = scew_parser_create();
67     scew_parser_ignore_whitespaces(parser, 1);
68
69         FILE * fp = _tfopen(path, _T("r"));
70         if (fp)
71         {
72                 if (scew_parser_load_file_fp(parser, fp))
73                 {
74                         tree = scew_parser_tree(parser);
75
76                         scew_element * root = GetRootElement(tree);
77                         if (root)
78                         {
79                                 // Currently our content is paths, so expect
80                                 // having paths in valid project file!
81                                 if (GetPathsData(root))
82                                         loaded = TRUE;
83                         };
84                 }
85                 scew_tree_free(tree);
86
87                 /* Frees the SCEW parser */
88                 scew_parser_free(parser);
89                 fclose(fp);
90         }
91         return loaded;
92 }
93
94 /** 
95  * @brief Return project file XML's root element.
96  * @param [in] tree XML tree we got from the parser.
97  * @return Root element pointer.
98  */
99 scew_element* ProjectFile::GetRootElement(scew_tree * tree)
100 {
101         scew_element * root = NULL;
102
103         if (tree != NULL)
104         {
105                 root = scew_tree_root(tree);
106         }
107
108         if (root != NULL)
109         {
110                 // Make sure we have correct root element
111                 if (_tcscmp(Root_element_name, scew_element_name(root)) != 0)
112                 {
113                         root = NULL;
114                 }
115         }
116         return root;
117 }
118
119 /** 
120  * @brief Reads the paths data from the XML data.
121  * This function reads the paths data inside given element in XML data.
122  * @param [in] parent Parent element for the paths data.
123  * @return TRUE if pathdata was found from the file.
124  */
125 BOOL ProjectFile::GetPathsData(scew_element * parent)
126 {
127         BOOL bFoundPaths = FALSE;
128         scew_element *paths = NULL;
129
130         if (parent != NULL)
131         {
132                 paths = scew_element_by_name(parent, Paths_element_name);
133         }
134
135         if (paths != NULL)
136         {
137                 bFoundPaths = TRUE;
138                 scew_element *left = NULL;
139                 scew_element *right = NULL;
140                 scew_element *filter = NULL;
141                 scew_element *subfolders = NULL;
142                 scew_element *left_ro = NULL;
143                 scew_element *right_ro = NULL;
144
145                 left = scew_element_by_name(paths, Left_element_name);
146                 right = scew_element_by_name(paths, Right_element_name);
147                 filter = scew_element_by_name(paths, Filter_element_name);
148                 subfolders = scew_element_by_name(paths, Subfolders_element_name);
149                 left_ro = scew_element_by_name(paths, Left_ro_element_name);
150                 right_ro = scew_element_by_name(paths, Right_ro_element_name);
151
152                 if (left)
153                 {
154                         LPCTSTR path = NULL;
155                         path = scew_element_contents(left);
156                         m_leftFile = path;
157                         m_bHasLeft = TRUE;
158                 }
159                 if (right)
160                 {
161                         LPCTSTR path = NULL;
162                         path = scew_element_contents(right);
163                         m_rightFile = path;
164                         m_bHasRight = TRUE;
165                 }
166                 if (filter)
167                 {
168                         LPCTSTR filtername = NULL;
169                         filtername = scew_element_contents(filter);
170                         m_filter = filtername;
171                         m_bHasFilter = TRUE;
172                 }
173                 if (subfolders)
174                 {
175                         LPCTSTR folders = NULL;
176                         folders = scew_element_contents(subfolders);
177                         m_subfolders = _ttoi(folders);
178                         m_bHasSubfolders = TRUE;
179                 }
180                 if (left_ro)
181                 {
182                         LPCTSTR readonly = NULL;
183                         readonly = scew_element_contents(left_ro);
184                         m_bLeftReadOnly = (_ttoi(readonly) != 0);
185                 }
186                 if (right_ro)
187                 {
188                         LPCTSTR readonly = NULL;
189                         readonly = scew_element_contents(right_ro);
190                         m_bRightReadOnly = (_ttoi(readonly) != 0);
191                 }
192         }
193         return bFoundPaths;
194 }
195
196 /** 
197  * @brief Save data from member variables to path-file.
198  * @param [in] path Path to project file.
199  * @param [out] sError Error string if error happened.
200  * @return TRUE if saving succeeded, FALSE if error happened.
201  */
202 BOOL ProjectFile::Save(LPCTSTR path, CString *sError)
203 {
204         BOOL success = TRUE;
205         scew_tree* tree = NULL;
206         scew_element* root = NULL;
207         scew_element* paths = NULL;
208
209         tree = scew_tree_create();
210         root = scew_tree_add_root(tree, Root_element_name);
211         if (root != NULL)
212         {
213                 paths = AddPathsElement(root);
214         }
215         else
216                 success = FALSE;
217
218         if (paths != NULL)
219         {
220                 AddPathsContent(paths);
221         }
222         else
223                 success = FALSE;
224         
225         scew_tree_set_xml_encoding(tree, _T("UTF-8"));
226
227         // Set the XML file standalone
228         scew_tree_set_xml_standalone(tree, 1);
229
230         FILE * fp = _tfopen(path, _T("w"));
231         if (fp)
232         {
233                 if (!scew_writer_tree_fp(tree, fp))
234                 {
235                         success = FALSE;
236                         *sError = LoadResString(IDS_FILEWRITE_ERROR);
237                 }
238                 fclose(fp);
239         }
240         else
241         {
242                 success = FALSE;
243         }
244         
245         /* Frees the SCEW tree */
246         scew_tree_free(tree);
247
248         if (success == FALSE)
249         {
250                 *sError = LoadResString(IDS_FILEWRITE_ERROR);
251         }
252         return success;
253 }
254
255 /**
256  * @brief Add paths element into XML tree.
257  * @param [in] parent Parent element for the paths element.
258  * @return pointer to added paths element.
259  */
260 scew_element* ProjectFile::AddPathsElement(scew_element * parent)
261 {
262         scew_element* element = NULL;
263         element = scew_element_add(parent, Paths_element_name);
264         return element;
265 }
266
267 /**
268  * @brief Add paths data to the XML tree.
269  * This function adds our paths data to the XML tree.
270  * @param [in] parent Parent element for paths data.
271  * @return TRUE if we succeeded, FALSE otherwise.
272  */
273 BOOL ProjectFile::AddPathsContent(scew_element * parent)
274 {
275         scew_element* element = NULL;
276
277         if (!m_leftFile.IsEmpty())
278         {
279                 LPCTSTR path;
280                 element = scew_element_add(parent, Left_element_name);
281                 path = m_leftFile.GetBuffer(MAX_PATH);
282                 scew_element_set_contents(element, path);
283                 m_leftFile.ReleaseBuffer();
284         }
285
286         if (!m_rightFile.IsEmpty())
287         {
288                 LPCTSTR path;
289                 element = scew_element_add(parent, Right_element_name);
290                 path = m_rightFile.GetBuffer(MAX_PATH);
291                 scew_element_set_contents(element, path);
292                 m_rightFile.ReleaseBuffer();
293         }
294
295         if (!m_filter.IsEmpty())
296         {
297                 LPCTSTR filter;
298                 element = scew_element_add(parent, Filter_element_name);
299                 filter = m_filter.GetBuffer(MAX_PATH);
300                 scew_element_set_contents(element, filter);
301                 m_filter.ReleaseBuffer();
302         }
303
304         element = scew_element_add(parent, Subfolders_element_name);
305         if (m_subfolders != 0)
306                 scew_element_set_contents(element, _T("1"));
307         else
308                 scew_element_set_contents(element, _T("0"));
309
310         element = scew_element_add(parent, Left_ro_element_name);
311         if (m_bLeftReadOnly)
312                 scew_element_set_contents(element, _T("1"));
313         else
314                 scew_element_set_contents(element, _T("0"));
315
316         element = scew_element_add(parent, Right_ro_element_name);
317         if (m_bRightReadOnly)
318                 scew_element_set_contents(element, _T("1"));
319         else
320                 scew_element_set_contents(element, _T("0"));
321
322         return TRUE;
323 }
324
325 /** 
326  * @brief Returns if left path is defined in project file.
327  * @return TRUE if project file has left path.
328  */
329 BOOL ProjectFile::HasLeft() const
330 {
331         return m_bHasLeft;
332 }
333
334 /** 
335  * @brief Returns if right path is defined in project file.
336  * @return TRUE if project file has right path.
337  */
338 BOOL ProjectFile::HasRight() const
339 {
340         return m_bHasRight;
341 }
342
343 /** 
344  * @brief Returns if filter is defined in project file.
345  * @return TRUE if project file has filter.
346  */
347 BOOL ProjectFile::HasFilter() const
348 {
349         return m_bHasFilter;
350 }
351
352 /** 
353  * @brief Returns if subfolder is defined in projectfile.
354  * @return TRUE if project file has subfolder definition.
355  */
356 BOOL ProjectFile::HasSubfolders() const
357 {
358         return m_bHasSubfolders;
359 }
360
361 /** 
362  * @brief Returns left path.
363  * @param [out] pReadOnly TRUE if readonly was specified for path.
364  */
365 CString ProjectFile::GetLeft(BOOL * pReadOnly /*=NULL*/) const
366 {
367         if (pReadOnly)
368                 *pReadOnly = m_bLeftReadOnly;
369         return m_leftFile;
370 }
371
372 /** 
373  * @brief Returns if left path is specified read-only.
374  */
375 BOOL ProjectFile::GetLeftReadOnly() const
376 {
377         return m_bLeftReadOnly;
378 }
379
380 /** 
381  * @brief Set left path, returns old left path.
382  * @param [in] sLeft Left path.
383  * @param [in] bReadOnly Will path be recorded read-only?
384  */
385 CString ProjectFile::SetLeft(const CString& sLeft, const BOOL * pReadOnly /*=NULL*/)
386 {
387         CString sLeftOld = GetLeft();
388         m_leftFile = sLeft;
389         if (pReadOnly)
390                 m_bLeftReadOnly = *pReadOnly;
391
392         return sLeftOld;
393 }
394
395 /** 
396  * @brief Returns right path.
397  * @param [out] pReadOnly TRUE if readonly was specified for path.
398  */
399 CString ProjectFile::GetRight(BOOL * pReadOnly /*=NULL*/) const
400 {
401         if (pReadOnly)
402                 *pReadOnly = m_bRightReadOnly;
403         return m_rightFile;
404 }
405
406 /** 
407  * @brief Returns if right path is specified read-only.
408  */
409 BOOL ProjectFile::GetRightReadOnly() const
410 {
411         return m_bRightReadOnly;
412 }
413
414 /** 
415  * @brief Set right path, returns old right path.
416  * @param [in] sRight Right path.
417  * @param [in] bReadOnly Will path be recorded read-only?
418  */
419 CString ProjectFile::SetRight(const CString& sRight, const BOOL * pReadOnly /*=NULL*/)
420 {
421         CString sRightOld = GetRight();
422         m_rightFile = sRight;
423         if (pReadOnly)
424                 m_bRightReadOnly = *pReadOnly;
425
426         return sRightOld;
427 }
428
429 /** 
430  * @brief Returns filter.
431  */
432 CString ProjectFile::GetFilter() const
433 {
434         return m_filter;
435 }
436
437 /** 
438  * @brief Set filter, returns old filter.
439  */
440 CString ProjectFile::SetFilter(const CString& sFilter)
441 {
442         CString sFilterOld = GetFilter();
443         m_filter = sFilter;
444
445         return sFilterOld;
446 }
447
448 /** 
449  * @brief Returns subfolder included -setting.
450  */
451 int ProjectFile::GetSubfolders() const
452 {
453         return m_subfolders;
454 }
455
456 /** 
457  * @brief set subfolder, returns old subfolder value.
458  */
459 int ProjectFile::SetSubfolders(const int iSubfolder)
460 {
461         int iSubfoldersOld = GetSubfolders(); 
462         m_subfolders = iSubfolder ? 1 : 0;
463
464         return iSubfoldersOld;
465 }
466
467 /** 
468  * @brief Returns left and right paths and recursive from project file
469  * 
470  * @param [out] sLeft Left path
471  * @param [out] sRight Right path
472  * @param [out] bSubFolders If TRUE subfolders included (recursive compare)
473  */
474 void ProjectFile::GetPaths(CString & sLeft, CString & sRight,
475         BOOL & bSubfolders) const
476 {
477         if (HasLeft())
478                 sLeft = GetLeft();
479         if (HasRight())
480                 sRight = GetRight();
481         if (HasSubfolders())
482                 bSubfolders = (GetSubfolders() == 1);
483 }