1 /////////////////////////////////////////////////////////////////////////////
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.
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.
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 /////////////////////////////////////////////////////////////////////////////
18 * @file ProjectFile.cpp
20 * @brief Implementation file for ProjectFile class.
22 // RCS ID line follows -- this is updated by CVS
26 #include <scew/scew.h>
28 #include "ProjectFile.h"
30 // ATL conversion macro hack for UTF-8 conversion
31 #define UTF82W(lpa) (\
32 ((_lpa = lpa) == NULL) ? NULL : (\
33 _convert = (lstrlenA(_lpa)+1),\
34 AtlA2WHelper((LPWSTR) alloca(_convert*2), _lpa, _convert, CP_UTF8)))
36 #define W2UTF8(lpw) (\
37 ((_lpw = lpw) == NULL) ? NULL : (\
38 _convert = (lstrlenW(_lpw)+1)*6,\
39 AtlW2AHelper((LPSTR) alloca(_convert), _lpw, _convert, CP_UTF8)))
41 #define UTF82A(lpu) W2A(UTF82W(lpu))
42 #define A2UTF8(lpa) W2UTF8(A2W(lpa))
44 # define UTF82T(lpu) UTF82W(lpu)
45 # define T2UTF8(lpw) W2UTF8(lpw)
47 # define UTF82T(lpu) UTF82A(lpu)
48 # define T2UTF8(lpw) A2UTF8(lpw)
51 // Constants for xml element names
52 const char Root_element_name[] = "project";
53 const char Paths_element_name[] = "paths";
54 const char Left_element_name[] = "left";
55 const char Right_element_name[] = "right";
56 const char Filter_element_name[] = "filter";
57 const char Subfolders_element_name[] = "subfolders";
58 const char Left_ro_element_name[] = "left-readonly";
59 const char Right_ro_element_name[] = "right-readonly";
62 * @brief Standard constructor.
64 ProjectFile::ProjectFile()
68 , m_bHasSubfolders(FALSE)
70 , m_bLeftReadOnly(FALSE)
71 , m_bRightReadOnly(FALSE)
76 * @brief Open given path-file and read data from it to member variables.
77 * @param [in] path Path to project file.
78 * @param [out] sError Error string if error happened.
79 * @return TRUE if reading succeeded, FALSE if error happened.
81 BOOL ProjectFile::Read(LPCTSTR path, CString *sError)
84 scew_tree* tree = NULL;
85 scew_parser* parser = NULL;
87 parser = scew_parser_create();
88 scew_parser_ignore_whitespaces(parser, 1);
90 FILE * fp = _tfopen(path, _T("r"));
93 if (scew_parser_load_file_fp(parser, fp))
95 tree = scew_parser_tree(parser);
97 scew_element * root = GetRootElement(tree);
100 // Currently our content is paths, so expect
101 // having paths in valid project file!
102 if (GetPathsData(root))
106 scew_tree_free(tree);
108 /* Frees the SCEW parser */
109 scew_parser_free(parser);
116 * @brief Return project file XML's root element.
117 * @param [in] tree XML tree we got from the parser.
118 * @return Root element pointer.
120 scew_element* ProjectFile::GetRootElement(scew_tree * tree)
122 scew_element * root = NULL;
126 root = scew_tree_root(tree);
131 // Make sure we have correct root element
132 if (strcmp(Root_element_name, scew_element_name(root)) != 0)
141 * @brief Reads the paths data from the XML data.
142 * This function reads the paths data inside given element in XML data.
143 * @param [in] parent Parent element for the paths data.
144 * @return TRUE if pathdata was found from the file.
146 BOOL ProjectFile::GetPathsData(scew_element * parent)
149 BOOL bFoundPaths = FALSE;
150 scew_element *paths = NULL;
154 paths = scew_element_by_name(parent, Paths_element_name);
160 scew_element *left = NULL;
161 scew_element *right = NULL;
162 scew_element *filter = NULL;
163 scew_element *subfolders = NULL;
164 scew_element *left_ro = NULL;
165 scew_element *right_ro = NULL;
167 left = scew_element_by_name(paths, Left_element_name);
168 right = scew_element_by_name(paths, Right_element_name);
169 filter = scew_element_by_name(paths, Filter_element_name);
170 subfolders = scew_element_by_name(paths, Subfolders_element_name);
171 left_ro = scew_element_by_name(paths, Left_ro_element_name);
172 right_ro = scew_element_by_name(paths, Right_ro_element_name);
177 path = scew_element_contents(left);
178 m_leftFile = UTF82T(path);
184 path = scew_element_contents(right);
185 m_rightFile = UTF82T(path);
190 LPCSTR filtername = NULL;
191 filtername = scew_element_contents(filter);
192 m_filter = UTF82T(filtername);
197 LPCSTR folders = NULL;
198 folders = scew_element_contents(subfolders);
199 m_subfolders = atoi(folders);
200 m_bHasSubfolders = TRUE;
204 LPCSTR readonly = NULL;
205 readonly = scew_element_contents(left_ro);
206 m_bLeftReadOnly = (atoi(readonly) != 0);
210 LPCSTR readonly = NULL;
211 readonly = scew_element_contents(right_ro);
212 m_bRightReadOnly = (atoi(readonly) != 0);
219 * @brief Save data from member variables to path-file.
220 * @param [in] path Path to project file.
221 * @param [out] sError Error string if error happened.
222 * @return TRUE if saving succeeded, FALSE if error happened.
224 BOOL ProjectFile::Save(LPCTSTR path, CString *sError)
227 scew_tree* tree = NULL;
228 scew_element* root = NULL;
229 scew_element* paths = NULL;
231 tree = scew_tree_create();
232 root = scew_tree_add_root(tree, Root_element_name);
235 paths = AddPathsElement(root);
242 AddPathsContent(paths);
247 scew_tree_set_xml_encoding(tree, "UTF-8");
249 // Set the XML file standalone
250 scew_tree_set_xml_standalone(tree, 1);
252 FILE * fp = _tfopen(path, _T("w"));
255 if (!scew_writer_tree_fp(tree, fp))
258 *sError = LoadResString(IDS_FILEWRITE_ERROR);
267 /* Frees the SCEW tree */
268 scew_tree_free(tree);
270 if (success == FALSE)
272 *sError = LoadResString(IDS_FILEWRITE_ERROR);
278 * @brief Add paths element into XML tree.
279 * @param [in] parent Parent element for the paths element.
280 * @return pointer to added paths element.
282 scew_element* ProjectFile::AddPathsElement(scew_element * parent)
284 scew_element* element = NULL;
285 element = scew_element_add(parent, Paths_element_name);
290 * @brief Add paths data to the XML tree.
291 * This function adds our paths data to the XML tree.
292 * @param [in] parent Parent element for paths data.
293 * @return TRUE if we succeeded, FALSE otherwise.
295 BOOL ProjectFile::AddPathsContent(scew_element * parent)
298 scew_element* element = NULL;
300 if (!m_leftFile.IsEmpty())
303 element = scew_element_add(parent, Left_element_name);
304 path = m_leftFile.GetBuffer(MAX_PATH);
305 scew_element_set_contents(element, T2UTF8(path));
306 m_leftFile.ReleaseBuffer();
309 if (!m_rightFile.IsEmpty())
312 element = scew_element_add(parent, Right_element_name);
313 path = m_rightFile.GetBuffer(MAX_PATH);
314 scew_element_set_contents(element, T2UTF8(path));
315 m_rightFile.ReleaseBuffer();
318 if (!m_filter.IsEmpty())
321 element = scew_element_add(parent, Filter_element_name);
322 filter = m_filter.GetBuffer(MAX_PATH);
323 scew_element_set_contents(element, T2UTF8(filter));
324 m_filter.ReleaseBuffer();
327 element = scew_element_add(parent, Subfolders_element_name);
328 if (m_subfolders != 0)
329 scew_element_set_contents(element, "1");
331 scew_element_set_contents(element, "0");
333 element = scew_element_add(parent, Left_ro_element_name);
335 scew_element_set_contents(element, "1");
337 scew_element_set_contents(element, "0");
339 element = scew_element_add(parent, Right_ro_element_name);
340 if (m_bRightReadOnly)
341 scew_element_set_contents(element, "1");
343 scew_element_set_contents(element, "0");
349 * @brief Returns if left path is defined in project file.
350 * @return TRUE if project file has left path.
352 BOOL ProjectFile::HasLeft() const
358 * @brief Returns if right path is defined in project file.
359 * @return TRUE if project file has right path.
361 BOOL ProjectFile::HasRight() const
367 * @brief Returns if filter is defined in project file.
368 * @return TRUE if project file has filter.
370 BOOL ProjectFile::HasFilter() const
376 * @brief Returns if subfolder is defined in projectfile.
377 * @return TRUE if project file has subfolder definition.
379 BOOL ProjectFile::HasSubfolders() const
381 return m_bHasSubfolders;
385 * @brief Returns left path.
386 * @param [out] pReadOnly TRUE if readonly was specified for path.
388 CString ProjectFile::GetLeft(BOOL * pReadOnly /*=NULL*/) const
391 *pReadOnly = m_bLeftReadOnly;
396 * @brief Returns if left path is specified read-only.
398 BOOL ProjectFile::GetLeftReadOnly() const
400 return m_bLeftReadOnly;
404 * @brief Set left path, returns old left path.
405 * @param [in] sLeft Left path.
406 * @param [in] bReadOnly Will path be recorded read-only?
408 CString ProjectFile::SetLeft(const CString& sLeft, const BOOL * pReadOnly /*=NULL*/)
410 CString sLeftOld = GetLeft();
413 m_bLeftReadOnly = *pReadOnly;
419 * @brief Returns right path.
420 * @param [out] pReadOnly TRUE if readonly was specified for path.
422 CString ProjectFile::GetRight(BOOL * pReadOnly /*=NULL*/) const
425 *pReadOnly = m_bRightReadOnly;
430 * @brief Returns if right path is specified read-only.
432 BOOL ProjectFile::GetRightReadOnly() const
434 return m_bRightReadOnly;
438 * @brief Set right path, returns old right path.
439 * @param [in] sRight Right path.
440 * @param [in] bReadOnly Will path be recorded read-only?
442 CString ProjectFile::SetRight(const CString& sRight, const BOOL * pReadOnly /*=NULL*/)
444 CString sRightOld = GetRight();
445 m_rightFile = sRight;
447 m_bRightReadOnly = *pReadOnly;
453 * @brief Returns filter.
455 CString ProjectFile::GetFilter() const
461 * @brief Set filter, returns old filter.
463 CString ProjectFile::SetFilter(const CString& sFilter)
465 CString sFilterOld = GetFilter();
472 * @brief Returns subfolder included -setting.
474 int ProjectFile::GetSubfolders() const
480 * @brief set subfolder, returns old subfolder value.
482 int ProjectFile::SetSubfolders(const int iSubfolder)
484 int iSubfoldersOld = GetSubfolders();
485 m_subfolders = iSubfolder ? 1 : 0;
487 return iSubfoldersOld;
491 * @brief Returns left and right paths and recursive from project file
493 * @param [out] sLeft Left path
494 * @param [out] sRight Right path
495 * @param [out] bSubFolders If TRUE subfolders included (recursive compare)
497 void ProjectFile::GetPaths(CString & sLeft, CString & sRight,
498 BOOL & bSubfolders) const
505 bSubfolders = (GetSubfolders() == 1);