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"
30 #include "ProjectFile.h"
32 // Constants for xml element names
33 const char Root_element_name[] = "project";
34 const char Paths_element_name[] = "paths";
35 const char Left_element_name[] = "left";
36 const char Middle_element_name[] = "middle";
37 const char Right_element_name[] = "right";
38 const char Filter_element_name[] = "filter";
39 const char Subfolders_element_name[] = "subfolders";
40 const char Left_ro_element_name[] = "left-readonly";
41 const char Middle_ro_element_name[] = "middle-readonly";
42 const char Right_ro_element_name[] = "right-readonly";
45 static String UTF82T(const char *str)
47 TCHAR *tstr = ucr::convertUTF8toT(str ? str : "");
53 static std::string T2UTF8(const TCHAR *str)
55 char *utf8 = (char *)ucr::convertTtoUTF8(str ? str : _T(""));
56 std::string newstr(utf8);
62 * @brief Standard constructor.
64 ProjectFile::ProjectFile()
69 , m_bHasSubfolders(FALSE)
71 , m_bLeftReadOnly(FALSE)
72 , m_bMiddleReadOnly(FALSE)
73 , m_bRightReadOnly(FALSE)
78 * @brief Open given path-file and read data from it to member variables.
79 * @param [in] path Path to project file.
80 * @param [out] sError Error string if error happened.
81 * @return TRUE if reading succeeded, FALSE if error happened.
83 BOOL ProjectFile::Read(LPCTSTR path, String *sError)
86 scew_tree* tree = NULL;
87 scew_parser* parser = NULL;
89 parser = scew_parser_create();
90 scew_parser_ignore_whitespaces(parser, 1);
92 scew_reader *reader = NULL;
93 FILE * fp = _tfopen(path, _T("r"));
96 reader = scew_reader_fp_create(fp);
99 tree = scew_parser_load (parser, reader);
103 scew_element * root = GetRootElement(tree);
106 // Currently our content is paths, so expect
107 // having paths in valid project file!
108 if (GetPathsData(root))
114 scew_tree_free(tree);
115 scew_reader_free(reader);
117 /* Frees the SCEW parser */
118 scew_parser_free(parser);
125 * @brief Return project file XML's root element.
126 * @param [in] tree XML tree we got from the parser.
127 * @return Root element pointer.
129 scew_element* ProjectFile::GetRootElement(scew_tree * tree)
131 scew_element * root = NULL;
135 root = scew_tree_root(tree);
140 // Make sure we have correct root element
141 if (strcmp(Root_element_name, scew_element_name(root)) != 0)
150 * @brief Reads the paths data from the XML data.
151 * This function reads the paths data inside given element in XML data.
152 * @param [in] parent Parent element for the paths data.
153 * @return TRUE if pathdata was found from the file.
155 BOOL ProjectFile::GetPathsData(scew_element * parent)
157 BOOL bFoundPaths = FALSE;
158 scew_element *paths = NULL;
162 paths = scew_element_by_name(parent, Paths_element_name);
168 scew_element *left = NULL;
169 scew_element *middle = NULL;
170 scew_element *right = NULL;
171 scew_element *filter = NULL;
172 scew_element *subfolders = NULL;
173 scew_element *left_ro = NULL;
174 scew_element *middle_ro = NULL;
175 scew_element *right_ro = NULL;
177 left = scew_element_by_name(paths, Left_element_name);
178 middle = scew_element_by_name(paths, Middle_element_name);
179 right = scew_element_by_name(paths, Right_element_name);
180 filter = scew_element_by_name(paths, Filter_element_name);
181 subfolders = scew_element_by_name(paths, Subfolders_element_name);
182 left_ro = scew_element_by_name(paths, Left_ro_element_name);
183 middle_ro = scew_element_by_name(paths, Middle_ro_element_name);
184 right_ro = scew_element_by_name(paths, Right_ro_element_name);
189 path = scew_element_contents(left);
190 m_paths.SetLeft(UTF82T(path).c_str());
196 path = scew_element_contents(middle);
197 m_paths.SetMiddle(UTF82T(path).c_str());
203 path = scew_element_contents(right);
204 m_paths.SetRight(UTF82T(path).c_str());
209 LPCSTR filtername = NULL;
210 filtername = scew_element_contents(filter);
211 m_filter = UTF82T(filtername);
216 LPCSTR folders = NULL;
217 folders = scew_element_contents(subfolders);
218 m_subfolders = atoi(folders);
219 m_bHasSubfolders = TRUE;
223 LPCSTR readonly = NULL;
224 readonly = scew_element_contents(left_ro);
225 m_bLeftReadOnly = (atoi(readonly) != 0);
229 LPCSTR readonly = NULL;
230 readonly = scew_element_contents(middle_ro);
231 m_bMiddleReadOnly = (atoi(readonly) != 0);
235 LPCSTR readonly = NULL;
236 readonly = scew_element_contents(right_ro);
237 m_bRightReadOnly = (atoi(readonly) != 0);
244 * @brief Save data from member variables to path-file.
245 * @param [in] path Path to project file.
246 * @param [out] sError Error string if error happened.
247 * @return TRUE if saving succeeded, FALSE if error happened.
249 BOOL ProjectFile::Save(LPCTSTR path, String *sError)
252 scew_tree* tree = NULL;
253 scew_element* root = NULL;
254 scew_element* paths = NULL;
256 tree = scew_tree_create();
257 root = scew_tree_set_root(tree, Root_element_name);
260 paths = AddPathsElement(root);
267 AddPathsContent(paths);
272 scew_tree_set_xml_encoding(tree, "UTF-8");
274 scew_writer *writer = NULL;
275 scew_printer *printer = NULL;
276 FILE * fp = _tfopen(path, _T("w"));
279 writer = scew_writer_fp_create(fp);
282 printer = scew_printer_create(writer);
284 if (!scew_printer_print_tree(printer, tree) ||
285 !scew_printf(_XT("\n")))
288 *sError = LoadResString(IDS_FILEWRITE_ERROR);
294 *sError = LoadResString(IDS_FILEWRITE_ERROR);
303 /* Frees the SCEW tree */
304 scew_tree_free(tree);
305 scew_writer_free(writer);
306 scew_printer_free(printer);
308 if (success == FALSE)
310 *sError = LoadResString(IDS_FILEWRITE_ERROR);
316 * @brief Add paths element into XML tree.
317 * @param [in] parent Parent element for the paths element.
318 * @return pointer to added paths element.
320 scew_element* ProjectFile::AddPathsElement(scew_element * parent)
322 scew_element* element = NULL;
323 element = scew_element_add(parent, Paths_element_name);
328 * @brief Covert characters that are unsafe for use in XML
329 * @param [in] str The string to be converted
330 * @return The converted string
332 static String EscapeXML(const String &str)
334 String escapedStr = str;
335 string_replace(escapedStr, _T("&"), _T("&"));
336 string_replace(escapedStr, _T("<"), _T("<"));
337 string_replace(escapedStr, _T(">"), _T(">"));
342 * @brief Add paths data to the XML tree.
343 * This function adds our paths data to the XML tree.
344 * @param [in] parent Parent element for paths data.
345 * @return TRUE if we succeeded, FALSE otherwise.
347 BOOL ProjectFile::AddPathsContent(scew_element * parent)
349 scew_element* element = NULL;
351 if (!m_paths.GetLeft().empty())
353 element = scew_element_add(parent, Left_element_name);
354 scew_element_set_contents(element, T2UTF8(EscapeXML(m_paths.GetLeft()).c_str()).c_str());
357 if (!m_paths.GetMiddle().empty())
359 element = scew_element_add(parent, Middle_element_name);
360 scew_element_set_contents(element, T2UTF8(EscapeXML(m_paths.GetMiddle()).c_str()).c_str());
363 if (!m_paths.GetRight().empty())
365 element = scew_element_add(parent, Right_element_name);
366 scew_element_set_contents(element, T2UTF8(EscapeXML(m_paths.GetRight()).c_str()).c_str());
369 if (!m_filter.empty())
371 element = scew_element_add(parent, Filter_element_name);
372 String filter = m_filter;
373 scew_element_set_contents(element, T2UTF8(EscapeXML(filter).c_str()).c_str());
376 element = scew_element_add(parent, Subfolders_element_name);
377 if (m_subfolders != 0)
378 scew_element_set_contents(element, "1");
380 scew_element_set_contents(element, "0");
382 element = scew_element_add(parent, Left_ro_element_name);
384 scew_element_set_contents(element, "1");
386 scew_element_set_contents(element, "0");
388 if (!m_paths.GetMiddle().empty())
390 element = scew_element_add(parent, Middle_ro_element_name);
391 if (m_bMiddleReadOnly)
392 scew_element_set_contents(element, "1");
394 scew_element_set_contents(element, "0");
396 element = scew_element_add(parent, Right_ro_element_name);
397 if (m_bRightReadOnly)
398 scew_element_set_contents(element, "1");
400 scew_element_set_contents(element, "0");
406 * @brief Returns if left path is defined in project file.
407 * @return TRUE if project file has left path.
409 BOOL ProjectFile::HasLeft() const
415 * @brief Returns if middle path is defined.
417 BOOL ProjectFile::HasMiddle() const
423 * @brief Returns if right path is defined in project file.
424 * @return TRUE if project file has right path.
426 BOOL ProjectFile::HasRight() const
432 * @brief Returns if filter is defined in project file.
433 * @return TRUE if project file has filter.
435 BOOL ProjectFile::HasFilter() const
441 * @brief Returns if subfolder is defined in projectfile.
442 * @return TRUE if project file has subfolder definition.
444 BOOL ProjectFile::HasSubfolders() const
446 return m_bHasSubfolders;
450 * @brief Returns left path.
451 * @param [out] pReadOnly TRUE if readonly was specified for path.
454 String ProjectFile::GetLeft(BOOL * pReadOnly /*=NULL*/) const
457 *pReadOnly = m_bLeftReadOnly;
458 return m_paths.GetLeft();
462 * @brief Returns if left path is specified read-only.
463 * @return TRUE if left path is read-only, FALSE otherwise.
465 BOOL ProjectFile::GetLeftReadOnly() const
467 return m_bLeftReadOnly;
471 * @brief Set left path, returns old left path.
472 * @param [in] sLeft Left path.
473 * @param [in] bReadOnly Will path be recorded read-only?
475 void ProjectFile::SetLeft(const String& sLeft, const BOOL * pReadOnly /*=NULL*/)
477 m_paths.SetLeft(sLeft.c_str(), false);
479 m_bLeftReadOnly = *pReadOnly;
483 * @brief Returns middle path.
484 * @param [out] pReadOnly TRUE if readonly was specified for path.
486 String ProjectFile::GetMiddle(BOOL * pReadOnly /*=NULL*/) const
489 *pReadOnly = m_bMiddleReadOnly;
490 return m_paths.GetMiddle();
494 * @brief Returns if middle path is specified read-only.
496 BOOL ProjectFile::GetMiddleReadOnly() const
498 return m_bMiddleReadOnly;
502 * @brief Set middle path, returns old middle path.
503 * @param [in] sMiddle Middle path.
504 * @param [in] bReadOnly Will path be recorded read-only?
506 void ProjectFile::SetMiddle(const String& sMiddle, const BOOL * pReadOnly /*=NULL*/)
508 m_paths.SetMiddle(sMiddle.c_str(), false);
510 m_bMiddleReadOnly = *pReadOnly;
516 * @brief Returns right path.
517 * @param [out] pReadOnly TRUE if readonly was specified for path.
518 * @return Right path.
520 String ProjectFile::GetRight(BOOL * pReadOnly /*=NULL*/) const
523 *pReadOnly = m_bRightReadOnly;
524 return m_paths.GetRight();
528 * @brief Returns if right path is specified read-only.
529 * @return TRUE if right path is read-only, FALSE otherwise.
531 BOOL ProjectFile::GetRightReadOnly() const
533 return m_bRightReadOnly;
537 * @brief Set right path, returns old right path.
538 * @param [in] sRight Right path.
539 * @param [in] bReadOnly Will path be recorded read-only?
541 void ProjectFile::SetRight(const String& sRight, const BOOL * pReadOnly /*=NULL*/)
543 m_paths.SetRight(sRight.c_str(), false);
545 m_bRightReadOnly = *pReadOnly;
549 * @brief Returns filter.
550 * @return Filter string.
552 String ProjectFile::GetFilter() const
559 * @param [in] sFilter New filter string to set.
561 void ProjectFile::SetFilter(const String& sFilter)
567 * @brief Returns subfolder included -setting.
568 * @return != 0 if subfolders are included.
570 int ProjectFile::GetSubfolders() const
576 * @brief set subfolder.
577 * @param [in] iSubfolder New value for subfolder inclusion.
579 void ProjectFile::SetSubfolders(int iSubfolder)
581 m_subfolders = iSubfolder ? 1 : 0;
587 * @param [in] files Files in project
588 * @param [in] bSubFolders If TRUE subfolders included (recursive compare)
590 void ProjectFile::SetPaths(const PathContext& files, BOOL bSubfolders)
593 m_subfolders = bSubfolders;
597 * @brief Returns left and right paths and recursive from project file
599 * @param [out] files Files in project
600 * @param [out] bSubFolders If TRUE subfolders included (recursive compare)
602 void ProjectFile::GetPaths(PathContext& files, BOOL & bSubfolders) const
606 bSubfolders = (GetSubfolders() == 1);