OSDN Git Service

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