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 // ID line follows -- this is updated by CVS
23 // $Id: ProjectFile.cpp 7081 2010-01-01 20:33:30Z kimmov $
26 #include <scew/scew.h>
28 #include "UnicodeString.h"
29 #include "ProjectFile.h"
31 // Constants for xml element names
32 const char Root_element_name[] = "project";
33 const char Paths_element_name[] = "paths";
34 const char Left_element_name[] = "left";
35 const char Middle_element_name[] = "middle";
36 const char Right_element_name[] = "right";
37 const char Filter_element_name[] = "filter";
38 const char Subfolders_element_name[] = "subfolders";
39 const char Left_ro_element_name[] = "left-readonly";
40 const char Middle_ro_element_name[] = "middle-readonly";
41 const char Right_ro_element_name[] = "right-readonly";
44 static String UTF82T(const char *str)
46 TCHAR *tstr = ucr::convertUTF8toT(str ? str : "");
52 static std::string T2UTF8(const TCHAR *str)
54 char *utf8 = (char *)ucr::convertTtoUTF8(str ? str : _T(""));
55 std::string newstr(utf8);
61 * @brief Standard constructor.
63 ProjectFile::ProjectFile()
68 , m_bHasSubfolders(FALSE)
70 , m_bLeftReadOnly(FALSE)
71 , m_bMiddleReadOnly(FALSE)
72 , m_bRightReadOnly(FALSE)
77 * @brief Open given path-file and read data from it to member variables.
78 * @param [in] path Path to project file.
79 * @param [out] sError Error string if error happened.
80 * @return TRUE if reading succeeded, FALSE if error happened.
82 BOOL ProjectFile::Read(LPCTSTR path, String *sError)
85 scew_tree* tree = NULL;
86 scew_parser* parser = NULL;
88 parser = scew_parser_create();
89 scew_parser_ignore_whitespaces(parser, 1);
91 scew_reader *reader = NULL;
92 FILE * fp = _tfopen(path, _T("r"));
95 reader = scew_reader_fp_create(fp);
98 tree = scew_parser_load (parser, reader);
102 scew_element * root = GetRootElement(tree);
105 // Currently our content is paths, so expect
106 // having paths in valid project file!
107 if (GetPathsData(root))
113 scew_tree_free(tree);
114 scew_reader_free(reader);
116 /* Frees the SCEW parser */
117 scew_parser_free(parser);
124 * @brief Return project file XML's root element.
125 * @param [in] tree XML tree we got from the parser.
126 * @return Root element pointer.
128 scew_element* ProjectFile::GetRootElement(scew_tree * tree)
130 scew_element * root = NULL;
134 root = scew_tree_root(tree);
139 // Make sure we have correct root element
140 if (strcmp(Root_element_name, scew_element_name(root)) != 0)
149 * @brief Reads the paths data from the XML data.
150 * This function reads the paths data inside given element in XML data.
151 * @param [in] parent Parent element for the paths data.
152 * @return TRUE if pathdata was found from the file.
154 BOOL ProjectFile::GetPathsData(scew_element * parent)
156 BOOL bFoundPaths = FALSE;
157 scew_element *paths = NULL;
161 paths = scew_element_by_name(parent, Paths_element_name);
167 scew_element *left = NULL;
168 scew_element *middle = NULL;
169 scew_element *right = NULL;
170 scew_element *filter = NULL;
171 scew_element *subfolders = NULL;
172 scew_element *left_ro = NULL;
173 scew_element *middle_ro = NULL;
174 scew_element *right_ro = NULL;
176 left = scew_element_by_name(paths, Left_element_name);
177 middle = scew_element_by_name(paths, Middle_element_name);
178 right = scew_element_by_name(paths, Right_element_name);
179 filter = scew_element_by_name(paths, Filter_element_name);
180 subfolders = scew_element_by_name(paths, Subfolders_element_name);
181 left_ro = scew_element_by_name(paths, Left_ro_element_name);
182 middle_ro = scew_element_by_name(paths, Middle_ro_element_name);
183 right_ro = scew_element_by_name(paths, Right_ro_element_name);
188 path = scew_element_contents(left);
189 m_paths.SetLeft(UTF82T(path).c_str());
195 path = scew_element_contents(middle);
196 m_paths.SetMiddle(UTF82T(path).c_str());
202 path = scew_element_contents(right);
203 m_paths.SetRight(UTF82T(path).c_str());
208 LPCSTR filtername = NULL;
209 filtername = scew_element_contents(filter);
210 m_filter = UTF82T(filtername);
215 LPCSTR folders = NULL;
216 folders = scew_element_contents(subfolders);
217 m_subfolders = atoi(folders);
218 m_bHasSubfolders = TRUE;
222 LPCSTR readonly = NULL;
223 readonly = scew_element_contents(left_ro);
224 m_bLeftReadOnly = (atoi(readonly) != 0);
228 LPCSTR readonly = NULL;
229 readonly = scew_element_contents(middle_ro);
230 m_bMiddleReadOnly = (atoi(readonly) != 0);
234 LPCSTR readonly = NULL;
235 readonly = scew_element_contents(right_ro);
236 m_bRightReadOnly = (atoi(readonly) != 0);
243 * @brief Save data from member variables to path-file.
244 * @param [in] path Path to project file.
245 * @param [out] sError Error string if error happened.
246 * @return TRUE if saving succeeded, FALSE if error happened.
248 BOOL ProjectFile::Save(LPCTSTR path, String *sError)
251 scew_tree* tree = NULL;
252 scew_element* root = NULL;
253 scew_element* paths = NULL;
255 tree = scew_tree_create();
256 root = scew_tree_set_root(tree, Root_element_name);
259 paths = AddPathsElement(root);
266 AddPathsContent(paths);
271 scew_tree_set_xml_encoding(tree, "UTF-8");
273 scew_writer *writer = NULL;
274 scew_printer *printer = NULL;
275 FILE * fp = _tfopen(path, _T("w"));
278 writer = scew_writer_fp_create(fp);
281 printer = scew_printer_create(writer);
283 if (!scew_printer_print_tree(printer, tree) ||
284 !scew_printf(_XT("\n")))
287 *sError = LoadResString(IDS_FILEWRITE_ERROR);
293 *sError = LoadResString(IDS_FILEWRITE_ERROR);
302 /* Frees the SCEW tree */
303 scew_tree_free(tree);
304 scew_writer_free(writer);
305 scew_printer_free(printer);
307 if (success == FALSE)
309 *sError = LoadResString(IDS_FILEWRITE_ERROR);
315 * @brief Add paths element into XML tree.
316 * @param [in] parent Parent element for the paths element.
317 * @return pointer to added paths element.
319 scew_element* ProjectFile::AddPathsElement(scew_element * parent)
321 scew_element* element = NULL;
322 element = scew_element_add(parent, Paths_element_name);
327 * @brief Covert characters that are unsafe for use in XML
328 * @param [in] str The string to be converted
329 * @return The converted string
331 static String EscapeXML(const String &str)
333 String escapedStr = str;
334 string_replace(escapedStr, _T("&"), _T("&"));
335 string_replace(escapedStr, _T("<"), _T("<"));
336 string_replace(escapedStr, _T(">"), _T(">"));
341 * @brief Add paths data to the XML tree.
342 * This function adds our paths data to the XML tree.
343 * @param [in] parent Parent element for paths data.
344 * @return TRUE if we succeeded, FALSE otherwise.
346 BOOL ProjectFile::AddPathsContent(scew_element * parent)
348 scew_element* element = NULL;
350 if (!m_paths.GetLeft().empty())
352 element = scew_element_add(parent, Left_element_name);
353 scew_element_set_contents(element, T2UTF8(EscapeXML(m_paths.GetLeft()).c_str()).c_str());
356 if (!m_paths.GetMiddle().empty())
358 element = scew_element_add(parent, Middle_element_name);
359 scew_element_set_contents(element, T2UTF8(EscapeXML(m_paths.GetMiddle()).c_str()).c_str());
362 if (!m_paths.GetRight().empty())
364 element = scew_element_add(parent, Right_element_name);
365 scew_element_set_contents(element, T2UTF8(EscapeXML(m_paths.GetRight()).c_str()).c_str());
368 if (!m_filter.empty())
370 element = scew_element_add(parent, Filter_element_name);
371 String filter = m_filter;
372 scew_element_set_contents(element, T2UTF8(EscapeXML(filter).c_str()).c_str());
375 element = scew_element_add(parent, Subfolders_element_name);
376 if (m_subfolders != 0)
377 scew_element_set_contents(element, "1");
379 scew_element_set_contents(element, "0");
381 element = scew_element_add(parent, Left_ro_element_name);
383 scew_element_set_contents(element, "1");
385 scew_element_set_contents(element, "0");
387 if (!m_paths.GetMiddle().empty())
389 element = scew_element_add(parent, Middle_ro_element_name);
390 if (m_bMiddleReadOnly)
391 scew_element_set_contents(element, "1");
393 scew_element_set_contents(element, "0");
395 element = scew_element_add(parent, Right_ro_element_name);
396 if (m_bRightReadOnly)
397 scew_element_set_contents(element, "1");
399 scew_element_set_contents(element, "0");
405 * @brief Returns if left path is defined in project file.
406 * @return TRUE if project file has left path.
408 BOOL ProjectFile::HasLeft() const
414 * @brief Returns if middle path is defined.
416 BOOL ProjectFile::HasMiddle() const
422 * @brief Returns if right path is defined in project file.
423 * @return TRUE if project file has right path.
425 BOOL ProjectFile::HasRight() const
431 * @brief Returns if filter is defined in project file.
432 * @return TRUE if project file has filter.
434 BOOL ProjectFile::HasFilter() const
440 * @brief Returns if subfolder is defined in projectfile.
441 * @return TRUE if project file has subfolder definition.
443 BOOL ProjectFile::HasSubfolders() const
445 return m_bHasSubfolders;
449 * @brief Returns left path.
450 * @param [out] pReadOnly TRUE if readonly was specified for path.
453 String ProjectFile::GetLeft(BOOL * pReadOnly /*=NULL*/) const
456 *pReadOnly = m_bLeftReadOnly;
457 return m_paths.GetLeft();
461 * @brief Returns if left path is specified read-only.
462 * @return TRUE if left path is read-only, FALSE otherwise.
464 BOOL ProjectFile::GetLeftReadOnly() const
466 return m_bLeftReadOnly;
470 * @brief Set left path, returns old left path.
471 * @param [in] sLeft Left path.
472 * @param [in] bReadOnly Will path be recorded read-only?
474 void ProjectFile::SetLeft(const String& sLeft, const BOOL * pReadOnly /*=NULL*/)
476 m_paths.SetLeft(sLeft.c_str(), false);
478 m_bLeftReadOnly = *pReadOnly;
482 * @brief Returns middle path.
483 * @param [out] pReadOnly TRUE if readonly was specified for path.
485 String ProjectFile::GetMiddle(BOOL * pReadOnly /*=NULL*/) const
488 *pReadOnly = m_bMiddleReadOnly;
489 return m_paths.GetMiddle();
493 * @brief Returns if middle path is specified read-only.
495 BOOL ProjectFile::GetMiddleReadOnly() const
497 return m_bMiddleReadOnly;
501 * @brief Set middle path, returns old middle path.
502 * @param [in] sMiddle Middle path.
503 * @param [in] bReadOnly Will path be recorded read-only?
505 void ProjectFile::SetMiddle(const String& sMiddle, const BOOL * pReadOnly /*=NULL*/)
507 m_paths.SetMiddle(sMiddle.c_str(), false);
509 m_bMiddleReadOnly = *pReadOnly;
515 * @brief Returns right path.
516 * @param [out] pReadOnly TRUE if readonly was specified for path.
517 * @return Right path.
519 String ProjectFile::GetRight(BOOL * pReadOnly /*=NULL*/) const
522 *pReadOnly = m_bRightReadOnly;
523 return m_paths.GetRight();
527 * @brief Returns if right path is specified read-only.
528 * @return TRUE if right path is read-only, FALSE otherwise.
530 BOOL ProjectFile::GetRightReadOnly() const
532 return m_bRightReadOnly;
536 * @brief Set right path, returns old right path.
537 * @param [in] sRight Right path.
538 * @param [in] bReadOnly Will path be recorded read-only?
540 void ProjectFile::SetRight(const String& sRight, const BOOL * pReadOnly /*=NULL*/)
542 m_paths.SetRight(sRight.c_str(), false);
544 m_bRightReadOnly = *pReadOnly;
548 * @brief Returns filter.
549 * @return Filter string.
551 String ProjectFile::GetFilter() const
558 * @param [in] sFilter New filter string to set.
560 void ProjectFile::SetFilter(const String& sFilter)
566 * @brief Returns subfolder included -setting.
567 * @return != 0 if subfolders are included.
569 int ProjectFile::GetSubfolders() const
575 * @brief set subfolder.
576 * @param [in] iSubfolder New value for subfolder inclusion.
578 void ProjectFile::SetSubfolders(int iSubfolder)
580 m_subfolders = iSubfolder ? 1 : 0;
586 * @param [in] files Files in project
587 * @param [in] bSubFolders If TRUE subfolders included (recursive compare)
589 void ProjectFile::SetPaths(const PathContext& files, BOOL bSubfolders)
592 m_subfolders = bSubfolders;
596 * @brief Returns left and right paths and recursive from project file
598 * @param [out] files Files in project
599 * @param [out] bSubFolders If TRUE subfolders included (recursive compare)
601 void ProjectFile::GetPaths(PathContext& files, BOOL & bSubfolders) const
605 bSubfolders = (GetSubfolders() == 1);