Code::Blocks  SVN r11506
configmanager.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3  * http://www.gnu.org/licenses/lgpl-3.0.html
4  *
5  * $Revision: 11191 $
6  * $Id: configmanager.cpp 11191 2017-10-07 13:10:12Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/sdk/configmanager.cpp $
8  */
9 
10 #include "sdk_precomp.h"
11 
12 #ifndef CB_PRECOMP
13  #include "configmanager.h"
14  #include "globals.h"
15  #include "personalitymanager.h"
16  #include "cbexception.h"
17  #include "logmanager.h"
18  #include <wx/file.h>
19  #include <wx/dir.h>
20  #include <wx/log.h> // for wxSafeShowMessage()
21 #endif
22 
23 #include "crc32.h"
24 
25 #include <wx/url.h>
26 #include <wx/stream.h>
27 #include <wx/stdpaths.h>
28 #include <wx/filename.h>
29 
30 #ifdef __WXMSW__
31 #include <shlobj.h>
32 #endif
33 
34 #include "annoyingdialog.h"
35 
36 #if defined(__APPLE__) && defined(__MACH__)
37 #include <sys/param.h>
38 #include <mach-o/dyld.h>
39 #endif
40 
41 #ifdef __WXMAC__
42 #if wxCHECK_VERSION(3, 0, 0)
43 #include "wx/osx/core/cfstring.h"
44 #else
45 #include "wx/mac/corefoundation/cfstring.h"
46 #endif
47 #include "wx/intl.h"
48 
49 #include <CoreFoundation/CFBundle.h>
50 #include <CoreFoundation/CFURL.h>
51 #endif
52 
53 #include "tinywxuni.h"
54 #include <stdlib.h>
55 
56 #ifdef __linux__
57 #include <glib.h>
58 #endif // __linux__
59 
60 template<> CfgMgrBldr* Mgr<CfgMgrBldr>::instance = nullptr;
61 template<> bool Mgr<CfgMgrBldr>::isShutdown = false;
62 
65 
70 #ifdef CB_AUTOCONF
71 wxString ConfigManager::plugin_path_global;
72 #endif
75 
76 
77 namespace CfgMgrConsts
78 {
79  const wxString app_path(_T("app_path"));
80  const wxString data_path(_T("data_path"));
81  const wxString dotDot(_T(".."));
82  const int version = 1;
83 }
84 
85 
86 namespace
87 {
88  wxString DetermineExecutablePath()
89  {
90  #ifdef __WXMSW__
91  wxChar name[MAX_PATH];
92  GetModuleFileName(0L, name, MAX_PATH);
93  wxFileName fname(name);
94  return fname.GetPath(wxPATH_GET_VOLUME);
95  #else
96  #ifdef __linux__
97  char c[PATH_MAX+1];
98  char *p = realpath("/proc/self/exe", &c[0]);
99  if (p == nullptr)
100  return _T(".");
101  wxFileName fname(cbC2U(p));
102  return fname.GetPath(wxPATH_GET_VOLUME);
103  #elif defined(sun) || defined(__sun)
104  wxFileName fname(cbC2U(getexecname()));
105  return fname.GetPath(wxPATH_GET_VOLUME);
106  #elif defined(__APPLE__) && defined(__MACH__)
107  char path[MAXPATHLEN+1];
108  uint32_t path_len = MAXPATHLEN;
109  // SPI first appeared in Mac OS X 10.2
110  _NSGetExecutablePath(path, &path_len);
111  wxFileName fname(wxString(path, wxConvUTF8));
112  return fname.GetPath(wxPATH_GET_VOLUME);
113  #else
114  return _T(".");
115  #endif
116  #endif
117  }
118 
119  wxString DetermineResourcesPath()
120  {
121  #if defined(__WXMAC__)
122  CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
123  CFURLRef absoluteURL = CFURLCopyAbsoluteURL(resourcesURL); // relative -> absolute
124  CFRelease(resourcesURL);
125  CFStringRef cfStrPath = CFURLCopyFileSystemPath(absoluteURL,kCFURLPOSIXPathStyle);
126  CFRelease(absoluteURL);
127  #if wxCHECK_VERSION(3, 0, 0)
128  wxString str = wxCFStringRef(cfStrPath).AsString(wxLocale::GetSystemEncoding());
129  #else
130  wxString str = wxMacCFStringHolder(cfStrPath).AsString(wxLocale::GetSystemEncoding());
131  #endif
132  if (!str.Contains(wxString(_T("/Resources"))))
133  return ::DetermineExecutablePath() + _T("/.."); // not a bundle, use relative path
134  return str;
135  #else
136  return _T(".");
137  #endif
138  }
139 }
140 
141 
142 inline void ConfigManager::Collapse(wxString& str) const
143 {
144  const wxChar *src = str.c_str();
145  wxChar *dst = (wxChar*) src;
146  wxChar c;
147  size_t len = 0;
148 
149  while ((c = *src))
150  {
151  ++src;
152 
153  *dst = c;
154  ++dst;
155  ++len;
156 
157  if (c == _T('/'))
158  while (*src == _T('/'))
159  ++src;
160  }
161  str.Truncate(len);
162 }
163 
165 {}
166 
168 {}
169 
170 
171 
172 
173 /* ------------------------------------------------------------------------------------------------------------------
174 * "Builder pattern" class for ConfigManager
175 * Do not use this class - Manager::Get()->GetConfigManager() is a lot friendlier
176 */
177 
178 CfgMgrBldr::CfgMgrBldr() : doc(nullptr), volatile_doc(nullptr), r(false)
179 {
181 
182  TiXmlBase::SetCondenseWhiteSpace(false);
183  wxString personality(Manager::Get()->GetPersonalityManager()->GetPersonality());
184 
185  if (personality.StartsWith(_T("http://")))
186  {
187  SwitchToR(personality);
188  return;
189  }
190 
191  cfg = FindConfigFile(personality + _T(".conf"));
192 
193  if (cfg.IsEmpty())
194  {
195  cfg = ConfigManager::GetConfigFolder() + wxFILE_SEP_PATH + personality + _T(".conf");
196  doc = new TiXmlDocument();
197  doc->InsertEndChild(TiXmlDeclaration("1.0", "UTF-8", "yes"));
198  doc->InsertEndChild(TiXmlElement("CodeBlocksConfig"));
199  doc->FirstChildElement("CodeBlocksConfig")->SetAttribute("version", CfgMgrConsts::version);
200  return;
201  }
202  SwitchTo(cfg);
203 }
204 
205 
207 {
208 
209  wxString u(ConfigManager::GetUserDataFolder() + wxFILE_SEP_PATH + filename);
210  wxString exePath(::DetermineExecutablePath());
211  wxString e(exePath + wxFILE_SEP_PATH + filename);
212 
214  {
216  return e;
217  }
218  if (::wxFileExists(u))
219  {
220  return u;
221  }
222  return wxEmptyString;
223 }
224 
227 static void handleConfigError(TiXmlDocument &doc, const wxString &fileName, const wxString &additionalMessage)
228 {
229  wxString message;
230  if (doc.ErrorId())
231  {
232  message = wxString::Format(_("TinyXML error: %s\nIn file: %s\nAt row %d, column: %d.\n\n"),
233  cbC2U(doc.ErrorDesc()).c_str(), fileName.wx_str(),
234  doc.ErrorRow(), doc.ErrorCol());
235  }
236  message += additionalMessage;
237 
238  // Show a message box and ask the user to either abort or discard the old config.
239  wxMessageDialog dlg(Manager::Get()->GetAppWindow(),
240  message + _("\n\nDiscard old config file?"), _("Config file read error"),
242 #if wxCHECK_VERSION(3, 0, 0)
243  dlg.SetYesNoLabels(_("&Discard"), _("&Close"));
244 #endif
245  if (dlg.ShowModal() != wxID_YES)
246  cbThrow(message);
247 
248  doc.ClearError();
249  doc.InsertEndChild(TiXmlDeclaration("1.0", "UTF-8", "yes"));
250  doc.InsertEndChild(TiXmlElement("CodeBlocksConfig"));
251  doc.FirstChildElement("CodeBlocksConfig")->SetAttribute("version", CfgMgrConsts::version);
252 }
253 
254 void CfgMgrBldr::SwitchTo(const wxString& fileName)
255 {
256  doc = new TiXmlDocument();
257 
258  if (!TinyXML::LoadDocument(fileName, doc))
259  {
260  const wxString message = wxString::Format(_("Error reading config file: %s"),
261  fileName.wx_str());
262  handleConfigError(*doc, fileName, message);
263  }
264 
265  TiXmlElement* docroot = doc->FirstChildElement("CodeBlocksConfig");
266  if (!docroot)
267  {
268  const wxString message = wxString::Format(wxT("Cannot find docroot in config file '%s'"),
269  fileName.wx_str());
270  handleConfigError(*doc, fileName, message);
271  docroot = doc->FirstChildElement("CodeBlocksConfig");
272 
273  if (!docroot)
274  cbThrow(wxT("Something really bad happened while reading the config file. Aborting!"));
275  }
276 
277  const char *vers = docroot->Attribute("version");
278  if (!vers || atoi(vers) != 1)
279  cbMessageBox(_("ConfigManager encountered an unknown config file version. Continuing happily."), _("Warning"), wxICON_WARNING);
280 
281  doc->ClearError();
282 
283  wxString info;
284 #ifndef __GNUC__
285  info.Printf(_T( " application info:\n"
286  "\t svn_revision:\t%u\n"
287  "\t build_date:\t%s, %s "), ConfigManager::GetRevisionNumber(), wxT(__DATE__), wxT(__TIME__));
288 #else
289  info.Printf(_T( " application info:\n"
290  "\t svn_revision:\t%u\n"
291  "\t build_date:\t%s, %s\n"
292  "\t gcc_version:\t%d.%d.%d "), ConfigManager::GetRevisionNumber(), wxT(__DATE__), wxT(__TIME__),
293  __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
294 #endif
295 
296  if (platform::windows)
297  info.append(_T("\n\t Windows "));
298  if (platform::Linux)
299  info.append(_T("\n\t Linux "));
300  if (platform::macosx)
301  info.append(_T("\n\t Mac OS X "));
302  if (platform::Unix)
303  info.append(_T("\n\t Unix "));
304 
305  info.append(platform::unicode ? _T("Unicode ") : _T("ANSI "));
306 
307  TiXmlComment c;
308  c.SetValue((const char*) info.mb_str());
309 
310  TiXmlNode *firstchild = docroot->FirstChild();
311  if (firstchild && firstchild->ToComment())
312  {
313  docroot->RemoveChild(firstchild);
314  firstchild = docroot->FirstChild();
315  }
316 
317  if (firstchild)
318  docroot->InsertBeforeChild(firstchild, c);
319  else
320  docroot->InsertEndChild(c);
321 }
322 
323 void CfgMgrBldr::SwitchToR(const wxString& absFileName)
324 {
325  if (doc)
326  delete doc;
327  doc = new TiXmlDocument();
328  doc->ClearError();
329 
330  cfg = absFileName;
331 
332  wxURL url(absFileName);
334  if (url.GetError() == wxURL_NOERR)
335  {
336  wxInputStream *is = url.GetInputStream();
337  if (is && is->IsOk())
338  {
339  size_t size = is->GetSize();
340  wxString str;
341  #if wxCHECK_VERSION(3, 0, 0)
342  wxChar* c = wxStringBuffer(str, size);
343  #else
344  wxChar* c = str.GetWriteBuf(size);
345  #endif
346  is->Read(c, size);
347  #if !wxCHECK_VERSION(3, 0, 0)
348  str.UngetWriteBuf(size);
349  #endif
350 
351  doc = new TiXmlDocument();
352 
353  if (doc->Parse(cbU2C(str)))
354  {
355  doc->ClearError();
356  delete is;
357  return;
358  }
359  if (Manager::Get()->GetLogManager())
360  {
361  Manager::Get()->GetLogManager()->DebugLog(_T("##### Error loading or parsing remote config file"));
362  Manager::Get()->GetLogManager()->DebugLog(cbC2U(doc->ErrorDesc()));
363  doc->ClearError();
364  }
365  }
366  delete is;
367  }
368  cfg.Empty();
369  SwitchTo(wxEmptyString); // fall back
370 }
371 
373 {
374  NamespaceMap::iterator it;
375  for ( it = namespaces.begin(); it != namespaces.end(); ++it )
376  delete it->second;
377 
378  namespaces.clear();
379  Close();
380  delete volatile_doc;
381 }
382 
384 {
385  if (doc)
386  {
387  if (!cfg.StartsWith(_T("http://")))
388  {
389  bool done = false;
390  do
391  {
393  done = true;
394  else
395  {
396  AnnoyingDialog dlg(_("Error"),
397  F(_T("Could not save config file '%s'!"), cfg.wx_str()),
399  AnnoyingDialog::rtTWO, _("&Retry"), _("&Close"));
400  PlaceWindow(&dlg);
401  switch (dlg.ShowModal())
402  {
404  done = false;
405  break;
407  default:
408  done = true;
409  }
410  }
411  } while (!done);
412  }
413  else
414  {
415  // implement WebDAV another time
416  }
417  }
418 }
419 
421 {
422  Flush();
423 
424  if (doc)
425  delete doc;
426 
427  doc = nullptr;
428 }
429 
430 
432 {
433  return Get()->Build(name_space);
434 }
435 
436 
438 {
439  if (name_space.IsEmpty())
440  cbThrow(_T("You attempted to get a ConfigManager instance without providing a namespace."));
441 
442  wxCriticalSectionLocker locker(cs);
443  NamespaceMap::iterator it = namespaces.find(name_space);
444  if (it != namespaces.end())
445  return it->second;
446 
447  TiXmlElement* docroot;
448 
449  if (name_space.StartsWith(_T("volatile:")))
450  {
451  if (!volatile_doc)
452  {
453  volatile_doc = new TiXmlDocument();
454  volatile_doc->InsertEndChild(TiXmlElement("CodeBlocksConfig"));
455  volatile_doc->SetCondenseWhiteSpace(false);
456  }
457  docroot = volatile_doc->FirstChildElement("CodeBlocksConfig");
458  }
459  else
460  {
461  docroot = doc->FirstChildElement("CodeBlocksConfig");
462  if (!docroot)
463  {
464  wxString err(_("Fatal error parsing supplied configuration file.\nParser error message:\n"));
465  err << wxString::Format(_T("%s\nAt row %d, column: %d."), cbC2U(doc->ErrorDesc()).c_str(), doc->ErrorRow(), doc->ErrorCol());
466  cbThrow(err);
467  }
468  }
469 
470  TiXmlElement* root = docroot->FirstChildElement(cbU2C(name_space));
471 
472  if (!root) // namespace does not exist
473  {
474  docroot->InsertEndChild(TiXmlElement(cbU2C(name_space)));
475  root = docroot->FirstChildElement(cbU2C(name_space));
476  }
477 
478  if (!root) // now what!
479  cbThrow(_T("Unable to create namespace in document tree (actually not possible..?)"));
480 
481  ConfigManager *c = new ConfigManager(root);
482  namespaces[name_space] = c;
483 
484  return c;
485 }
486 
487 /*
488 * Hack to enable Turkish language. wxString::Upper will convert lowercase 'i' to \u0130 instead of \u0069 in Turkish locale,
489 * which will break the config file when used in a tag
490 */
491 inline void to_upper(wxString& s)
492 {
493  #if wxCHECK_VERSION(3, 0, 0)
494  wxStringCharType *p = const_cast<wxStringCharType*>(s.wx_str());
496  #else
497  wxChar *p = (wxChar*) s.c_str();
498  wxChar q;
499  #endif
500  size_t len = s.length()+1;
501  for (;--len;++p)
502  {
503  q = *p;
504  if (q >= 'a' && q <= 'z')
505  *p = q - 32;
506  }
507 }
508 
509 inline void to_lower(wxString& s)
510 {
511  #if wxCHECK_VERSION(3, 0, 0)
512  wxStringCharType *p = const_cast<wxStringCharType*>(s.wx_str());
514  #else
515  wxChar *p = (wxChar*) s.c_str();
516  wxChar q;
517  #endif
518  size_t len = s.length()+1;
519  for (;--len;++p)
520  {
521  q = *p;
522  if (q >= 'A' && q <= 'Z')
523  *p = q + 32;
524  }
525 }
526 
527 
528 /* ------------------------------------------------------------------------------------------------------------------
529 * Functions to retrieve system paths and locate data files in a defined, consistent way.
530 * Please note that the application determines app_path and data_path at runtime and passes the results
531 * to ConfigManager. GetExecutableFolder() and GetDataFolder() are therefore under normal conditions
532 * simply more efficient shortcuts for Read("app_path") and Read("data_path").
533 */
534 
536 {
537  return Manager::Get()->GetConfigManager(_T("app"))->Read(_T("network_proxy"));
538 }
539 
540 
542 {
543  static bool once = 1;
544 
545  if (once)
546  {
547  InitPaths();
548  once = false;
549  }
550 
551  switch (dir)
552  {
553  case sdHome:
555 
556  case sdBase:
558 
559  case sdTemp:
561 
562  case sdConfig:
564 
565  case sdCurrent:
567 
568  case sdPluginsGlobal:
569 #ifndef CB_AUTOCONF
570  return ConfigManager::data_path_global + wxFILE_SEP_PATH + _T("plugins");
571 #else
572  return ConfigManager::plugin_path_global;
573 #endif
574 
575  case sdPluginsUser:
576  return ConfigManager::data_path_user + wxFILE_SEP_PATH + _T("plugins");
577 
578  case sdScriptsGlobal:
579  return ConfigManager::data_path_global + wxFILE_SEP_PATH + _T("scripts");
580 
581  case sdScriptsUser:
582  return ConfigManager::data_path_user + wxFILE_SEP_PATH + _T("scripts");
583 
584  case sdDataGlobal:
586 
587  case sdDataUser:
589 
590  case sdPath:
591  case sdAllUser:
592  case sdAllGlobal:
593  case sdAllKnown:
594  default:
595  return wxEmptyString;
596  }
597 }
598 
600 {
601  if (has_alternate_user_data_path)
602  return alternate_user_data_path;
603 #ifdef __WINDOWS__
604  TCHAR buffer[MAX_PATH];
605  if (!ConfigManager::has_alternate_user_data_path && ::GetEnvironmentVariable(_T("APPDATA"), buffer, MAX_PATH))
606  return wxString::Format(_T("%s\\CodeBlocks"), buffer);
607  else
608  return wxStandardPathsBase::Get().GetUserDataDir();
609 #else
610 #ifdef __linux__
611  return wxString::FromUTF8(g_build_filename (g_get_user_config_dir(), "codeblocks", NULL));
612 #else
613  return wxStandardPathsBase::Get().GetUserDataDir();
614 #endif // __linux__
615 #endif // __WINDOWS__
616 }
617 
618 
619 bool ConfigManager::SetUserDataFolder(const wxString &user_data_path)
620 {
621  wxString udp = wxFileName::DirName(user_data_path).GetFullPath();
622  if (!CreateDirRecursively(udp))
623  {
624  cbMessageBox(wxString::Format(_("The --user-data-dir directory %s does not exist and could not be created. Please check the path and try again"),
625  user_data_path.c_str()), _("Command Line Error"));
626  return false;
627  }
628  has_alternate_user_data_path = true;
629  ConfigManager::alternate_user_data_path = udp;
630  return true;
631 }
632 
633 wxString ConfigManager::LocateDataFile(const wxString& filename, int search_dirs)
634 {
635  wxPathList searchPaths;
636 
637  // user dirs have precedence
638  if (search_dirs & sdPluginsUser)
639  searchPaths.Add(GetPluginsFolder(false));
640  if (search_dirs & sdScriptsUser)
641  searchPaths.Add(GetScriptsFolder(false));
642  if (search_dirs & sdDataUser)
643  searchPaths.Add(GetDataFolder(false));
644 
645  // then we have global dirs
646  if (search_dirs & sdPluginsGlobal)
647  searchPaths.Add(GetPluginsFolder(true));
648  if (search_dirs & sdScriptsGlobal)
649  searchPaths.Add(GetScriptsFolder(true));
650  if (search_dirs & sdDataGlobal)
651  searchPaths.Add(GetDataFolder(true));
652 
653  // rest of the dirs
654  if (search_dirs & sdCurrent)
655  searchPaths.Add(::wxGetCwd());
656  if (search_dirs & sdConfig)
657  searchPaths.Add(GetConfigFolder());
658  if (search_dirs & sdHome)
659  searchPaths.Add(GetHomeFolder());
660  if (search_dirs & sdBase)
661  searchPaths.Add(GetExecutableFolder());
662  if (search_dirs & sdTemp)
663  searchPaths.Add(GetTempFolder());
664 
665  // PATH env. var
666  if (search_dirs & sdPath)
667  searchPaths.AddEnvList(_T("PATH"));
668 
669  return searchPaths.FindValidPath(filename);
670 }
671 
672 
673 
674 /* ------------------------------------------------------------------------------------------------------------------
675 * ConfigManager
676 */
677 
678 ConfigManager::ConfigManager(TiXmlElement* r) : doc(r->GetDocument()), root(r), pathNode(r)
679 {
680 }
681 
682 
683 
684 
685 /* ------------------------------------------------------------------------------------------------------------------
686 * Configuration path handling
687 * Note that due to namespaces, you do no longer need to care about saving/restoring the current path in the normal case.
688 * Mostly, there will be only one module working with one namespace, and every namespace keeps track of its own path.
689 * Also, please note that GetPath() is more expensive than it seems (not a mere accessor to a member variable!), while
690 * SetPath() not only sets the current path, but also creates the respective nodes in the XML document if these don't exist.
691 */
692 
694 {
695  TiXmlElement *e = pathNode;
696  wxString ret;
697  ret.Alloc(64);
698 
699  ret = cbC2U(e->Value());
700  while ((e = e->Parent()->ToElement()) && e != root)
701  {
702  ret.Prepend(_T('/'));
703  ret.Prepend(cbC2U(e->Value()));
704  }
705  ret.Prepend(_T('/'));
706  return ret;
707 }
708 
710 {
711  wxString p(path + _T('/'));
712  pathNode = AssertPath(p);
713 }
714 
715 wxString ConfigManager::InvalidNameMessage(const wxString& what, const wxString& sub, TiXmlElement *localPath) const
716 {
717  wxString s;
718  s.Printf(_T("The %s %s (child of node \"%s\" in namespace \"%s\") does not meet the standard for path naming (must start with a letter)."),
719  what.c_str(),
720  sub.c_str(),
721  cbC2U(localPath->Value()).c_str(),
722  cbC2U(root->Value()).c_str());
723 
724  return s;
725 }
726 
727 
729 {
730  Collapse(path);
731 
732  wxString illegal(_T(" -:.\"\'$&()[]<>+#"));
733  size_t i = 0;
734  while ((i = path.find_first_of(illegal, i)) != wxString::npos)
735  path[i] = _T('_');
736 
737  TiXmlElement *localPath = pathNode ? pathNode : root;
738 
739  if (path.GetChar(0) == '/') // absolute path
740  {
741  localPath = root;
742  path = path.Mid(1);
743  }
744 
745  if (path.find(_T('/')) != wxString::npos) // need for path walking
746  to_lower(path);
747 
748  wxString sub;
749 
750  while (path.find(_T('/')) != wxString::npos)
751  {
752  sub = path.BeforeFirst(_T('/'));
753  path = path.AfterFirst(_T('/'));
754 
755  if (localPath != root && sub.IsSameAs(CfgMgrConsts::dotDot))
756  localPath = localPath->Parent()->ToElement();
757  else if (sub.GetChar(0) < _T('a') || sub.GetChar(0) > _T('z'))
758  {
759  cbThrow(InvalidNameMessage(_T("subpath"), sub, localPath));
760  }
761  else
762  {
763  TiXmlElement* n = localPath->FirstChildElement(cbU2C(sub));
764  if (n)
765  localPath = n;
766  else
767  localPath = (TiXmlElement*) localPath->InsertEndChild(TiXmlElement(cbU2C(sub)));
768  }
769  }
770 
771  to_upper(path);
772 
773  if (!path.IsEmpty() && (path.GetChar(0) < _T('A') || path.GetChar(0) > _T('Z')))
774  cbThrow(InvalidNameMessage(_T("key"), path, localPath));
775 
776  return localPath;
777 }
778 
779 
780 /* -----------------------------------------------------------------------------------------------------
781 * Clear all nodes from your namespace or delete the namespace alltogether (removing it from the config file).
782 * After Delete() returns, the pointer to your instance is invalid.
783 */
784 
786 {
787  root->Clear();
788 }
789 
791 {
792  CfgMgrBldr * bld = CfgMgrBldr::Get();
793  const wxString ns(cbC2U(root->Value()));
794 
795  root->Clear();
796  doc->RootElement()->RemoveChild(root);
797 
799  NamespaceMap::iterator it = bld->namespaces.find(ns);
800  if (it != bld->namespaces.end())
801  bld->namespaces.erase(it);
802 
803  delete this;
804 }
805 
807 {
808  CfgMgrBldr * bld = CfgMgrBldr::Get();
809  const wxString ns(cbC2U(root->Value()));
810 
811  if (!ns.IsSameAs(_T("app")))
812  cbThrow(_T("Illegal attempt to invoke DeleteAll()."));
813 
815  doc->RootElement()->Clear();
816  for (NamespaceMap::iterator it = bld->namespaces.begin(); it != bld->namespaces.end(); ++it)
817  delete it->second;
818 
819  bld->namespaces.clear();
820 }
821 
823 {
824  CfgMgrBldr * bld = CfgMgrBldr::Get();
826  bld->Flush();
827 }
828 
829 /* ------------------------------------------------------------------------------------------------------------------
830 * Utility functions for writing nodes
831 */
832 
833 TiXmlElement* ConfigManager::GetUniqElement(TiXmlElement* p, const wxString& q)
834 {
835  TiXmlElement* r;
836  if ((r = p->FirstChildElement(cbU2C(q))))
837  return r;
838 
839  return (TiXmlElement*)(p->InsertEndChild(TiXmlElement(cbU2C(q))));
840 }
841 
842 void ConfigManager::SetNodeText(TiXmlElement* n, const TiXmlText& t)
843 {
844  TiXmlNode *c = n->FirstChild();
845  if (c)
846  n->ReplaceChild(c, t);
847  else
848  n->InsertEndChild(t);
849 }
850 
851 
852 
853 /* ------------------------------------------------------------------------------------------------------------------
854 * Write and read values
855 * Regardless of namespaces, the string keys app_path and data_path always refer to the location of the application's executable
856 * and the data path, respectively. These values are never saved to the configuration, but kept in static variables.
857 * The application makes use of this by "writing" to the configuration file after determining these values at runtime.
858 */
859 void ConfigManager::Write(const wxString& name, const wxString& value, bool ignoreEmpty)
860 {
862  {
863  return;
864  }
865  else if (name.IsSameAs(CfgMgrConsts::data_path))
866  {
867  data_path_global = value;
868  return;
869  }
870  if (ignoreEmpty && value.IsEmpty())
871  {
872  UnSet(name);
873  return;
874  }
875 
876  wxString key(name);
877  TiXmlElement* e = AssertPath(key);
878 
879  TiXmlElement *str = GetUniqElement(e, key);
880 
881  TiXmlElement *s = GetUniqElement(str, _T("str"));
882 
883  TiXmlText t(value.mb_str(wxConvUTF8));
884  t.SetCDATA(true);
885  SetNodeText(s, t);
886 }
887 
888 void ConfigManager::Write(const wxString& key, const char* str)
889 {
890  /* NOTE (mandrav#1#): Do *not* remove 'false' from the call because in ANSI builds,
891  it matches this very function and overflows the stack... */
892  Write(key, cbC2U(str), false);
893 }
894 
895 wxString ConfigManager::Read(const wxString& name, const wxString& defaultVal)
896 {
898  return app_path;
899  else if (name.IsSameAs(CfgMgrConsts::data_path))
900  return data_path_global;
901 
902  wxString ret;
903 
904  if (Read(name, &ret))
905  return ret;
906  else
907  return defaultVal;
908 }
909 
910 bool ConfigManager::Read(const wxString& name, wxString* str)
911 {
913  {
914  str->assign(app_path);
915  return true;
916  }
917  else if (name.IsSameAs(CfgMgrConsts::data_path))
918  {
919  str->assign(data_path_global);
920  return true;
921  }
922 
923  wxString key(name);
924  TiXmlElement* e = AssertPath(key);
925 
926  TiXmlHandle parentHandle(e);
927  TiXmlText *t = (TiXmlText *) parentHandle.FirstChild(cbU2C(key)).FirstChild("str").FirstChild().Node();
928 
929  if (t)
930  {
931  str->assign(cbC2U(t->Value()));
932  return true;
933  }
934  return false;
935 }
936 
937 void ConfigManager::Write(const wxString& name, const wxColour& c)
938 {
939  wxString key(name);
940  TiXmlElement* e = AssertPath(key);
941 
942  TiXmlElement *leaf = GetUniqElement(e, key);
943 
944  TiXmlElement *s = GetUniqElement(leaf, _T("colour"));
945  if (c == wxNullColour)
946  {
947  s->SetAttribute("null", "true");
948  s->SetAttribute("r", 0);
949  s->SetAttribute("g", 0);
950  s->SetAttribute("b", 0);
951  }
952  else
953  {
954  s->SetAttribute("r", c.Red());
955  s->SetAttribute("g", c.Green());
956  s->SetAttribute("b", c.Blue());
957  }
958 }
959 
960 wxColour ConfigManager::ReadColour(const wxString& name, const wxColour& defaultVal)
961 {
962  wxColour ret;
963 
964  if (Read(name, &ret))
965  return ret;
966  else
967  return defaultVal;
968 }
969 
970 bool ConfigManager::Read(const wxString& name, wxColour* ret)
971 {
972  wxString key(name);
973  TiXmlElement* e = AssertPath(key);
974 
975  TiXmlHandle parentHandle(e);
976  TiXmlElement *c = (TiXmlElement *) parentHandle.FirstChild(cbU2C(key)).FirstChild("colour").Element();
977 
978  if (c)
979  {
980  const char *isNull = c->Attribute("null");
981  if (isNull && strcmp(isNull, "true") == 0)
982  {
983  *ret = wxNullColour;
984  return true;
985  }
986  else
987  {
988  int r, g, b;
989  if (c->QueryIntAttribute("r", &r) == TIXML_SUCCESS
990  && c->QueryIntAttribute("g", &g) == TIXML_SUCCESS
991  && c->QueryIntAttribute("b", &b) == TIXML_SUCCESS)
992  {
993  ret->Set(r, g, b);
994  return true;
995  }
996  }
997  }
998  *ret = wxNullColour;
999  return false;
1000 }
1001 
1002 void ConfigManager::Write(const wxString& name, int value)
1003 {
1004  wxString key(name);
1005  TiXmlElement* e = AssertPath(key);
1006  TiXmlElement *leaf = GetUniqElement(e, key);
1007 
1008  leaf->SetAttribute("int", value);
1009 }
1010 
1011 int ConfigManager::ReadInt(const wxString& name, int defaultVal)
1012 {
1013  int ret;
1014 
1015  if (Read(name, &ret))
1016  return ret;
1017  else
1018  return defaultVal;
1019 }
1020 
1021 bool ConfigManager::Read(const wxString& name, int* value)
1022 {
1023  wxString key(name);
1024  TiXmlElement* e = AssertPath(key);
1025 
1026  TiXmlHandle parentHandle(e);
1027  TiXmlElement *leaf = parentHandle.FirstChild(cbU2C(key)).Element();
1028 
1029  if (leaf)
1030  return leaf->QueryIntAttribute("int", value) == TIXML_SUCCESS;
1031  return false;
1032 }
1033 
1034 
1035 void ConfigManager::Write(const wxString& name, bool value)
1036 {
1037  wxString key(name);
1038  TiXmlElement* e = AssertPath(key);
1039  TiXmlElement *leaf = GetUniqElement(e, key);
1040 
1041  leaf->SetAttribute("bool", value ? "1" : "0");
1042 }
1043 
1044 bool ConfigManager::ReadBool(const wxString& name, bool defaultVal)
1045 {
1046  bool ret;
1047 
1048  if (Read(name, &ret))
1049  return ret;
1050  else
1051  return defaultVal;
1052 }
1053 
1054 bool ConfigManager::Read(const wxString& name, bool* value)
1055 {
1056  wxString key(name);
1057  TiXmlElement* e = AssertPath(key);
1058 
1059  TiXmlHandle parentHandle(e);
1060  TiXmlElement *leaf = parentHandle.FirstChild(cbU2C(key)).Element();
1061 
1062  if (leaf && leaf->Attribute("bool"))
1063  {
1064  *value = leaf->Attribute("bool")[0] == '1';
1065  return true;
1066  }
1067  return false;
1068 }
1069 
1070 
1071 void ConfigManager::Write(const wxString& name, double value)
1072 {
1073  wxString key(name);
1074  TiXmlElement* e = AssertPath(key);
1075  TiXmlElement *leaf = GetUniqElement(e, key);
1076 
1077  leaf->SetDoubleAttribute("double", value);
1078 }
1079 
1080 double ConfigManager::ReadDouble(const wxString& name, double defaultVal)
1081 {
1082  double ret;
1083 
1084  if (Read(name, &ret))
1085  return ret;
1086  else
1087  return defaultVal;
1088 }
1089 
1090 bool ConfigManager::Read(const wxString& name, double* value)
1091 {
1092  wxString key(name);
1093  TiXmlElement* e = AssertPath(key);
1094 
1095  TiXmlHandle parentHandle(e);
1096  TiXmlElement *leaf = parentHandle.FirstChild(cbU2C(key)).Element();
1097 
1098  if (leaf)
1099  return leaf->QueryDoubleAttribute("double", value) == TIXML_SUCCESS;
1100  return false;
1101 }
1102 
1103 
1104 void ConfigManager::Set(const wxString& name)
1105 {
1106  wxString key(name);
1107  TiXmlElement* e = AssertPath(key);
1108  GetUniqElement(e, key);
1109 }
1110 
1112 {
1113  wxString key(name);
1114  TiXmlElement* e = AssertPath(key);
1115 
1116  TiXmlNode *leaf = GetUniqElement(e, key);
1117  e->RemoveChild(leaf);
1118 }
1119 
1121 {
1122  wxString key(name);
1123  TiXmlElement* e = AssertPath(key);
1124 
1125  TiXmlHandle parentHandle(e);
1126  TiXmlElement *leaf = parentHandle.FirstChild(cbU2C(key)).Element();
1127 
1128  return leaf;
1129 }
1130 
1131 
1132 
1133 void ConfigManager::Write(const wxString& name, const wxArrayString& arrayString)
1134 {
1135  wxString key(name);
1136  TiXmlElement* e = AssertPath(key);
1137 
1138  TiXmlElement *leaf = GetUniqElement(e, key);
1139 
1140  TiXmlElement *as;
1141  as = GetUniqElement(leaf, _T("astr"));
1142  leaf->RemoveChild(as);
1143  as = GetUniqElement(leaf, _T("astr"));
1144 
1145  for (unsigned int i = 0; i < arrayString.GetCount(); ++i)
1146  {
1147  TiXmlElement s("s");
1148 
1149  TiXmlText t(arrayString[i].mb_str(wxConvUTF8));
1150  t.SetCDATA(true);
1151 
1152  s.InsertEndChild(t);
1153  as->InsertEndChild(s);
1154  }
1155 }
1156 
1157 void ConfigManager::Read(const wxString& name, wxArrayString *arrayString)
1158 {
1159  wxString key(name);
1160  TiXmlElement* e = AssertPath(key);
1161 
1162  TiXmlHandle parentHandle(e);
1163  TiXmlNode *asNode = parentHandle.FirstChild(cbU2C(key)).FirstChild("astr").Node();
1164 
1165  TiXmlNode *curr = nullptr;
1166  if (asNode)
1167  {
1168  while ((curr = asNode->IterateChildren("s", curr)))
1169  arrayString->Add(cbC2U(curr->FirstChild()->ToText()->Value()));
1170  }
1171 }
1172 
1174 {
1175  wxArrayString as;
1176  Read(name, &as);
1177  return as;
1178 }
1179 
1180 void ConfigManager::WriteBinary(const wxString& name, const wxString& source)
1181 {
1182  wxString key(name);
1183  TiXmlElement* e = AssertPath(key);
1184 
1185  TiXmlElement *str = GetUniqElement(e, key);
1186 
1187  TiXmlElement *s = GetUniqElement(str, _T("bin"));
1188  s->SetAttribute("crc", wxCrc32::FromString(source));
1189  SetNodeText(s, TiXmlText(wxBase64::Encode(source).mb_str(wxConvUTF8)));
1190 }
1191 
1192 void ConfigManager::WriteBinary(const wxString& name, void* ptr, size_t len)
1193 {
1194  wxString s((wxChar*)ptr, len);
1195  WriteBinary(name, s);
1196 }
1197 
1199 {
1200  wxString str;
1201  wxString key(name);
1202  TiXmlElement* e = AssertPath(key);
1203  unsigned int crc = 0;
1204 
1205  TiXmlHandle parentHandle(e);
1206  TiXmlElement* bin = parentHandle.FirstChild(cbU2C(key)).FirstChild("bin").Element();
1207 
1208  if (!bin)
1209  return wxEmptyString;
1210 
1211  if (bin->QueryIntAttribute("crc", (int*)&crc) != TIXML_SUCCESS)
1212  return wxEmptyString;
1213 
1214  if (const TiXmlText* t = bin->FirstChild()->ToText())
1215  {
1216  str.assign(cbC2U(t->Value()));
1217  str = wxBase64::Decode(str);
1218  if (crc == wxCrc32::FromString(str))
1219  return str;
1220  }
1221  return wxEmptyString;
1222 }
1223 
1224 
1226 {
1227  wxString key(path + _T('/')); // the trailing slash hack is required because AssertPath expects a key name
1228  TiXmlNode* e = AssertPath(key);
1229  wxArrayString ret;
1230 
1231  TiXmlElement *curr = nullptr;
1232  if (e)
1233  {
1234  while (e->IterateChildren(curr) && (curr = e->IterateChildren(curr)->ToElement()))
1235  {
1236  #if wxCHECK_VERSION(3, 0, 0)
1237  wxUniChar c = cbC2U(curr->Value())[0];
1238  #else
1239  wxChar c = *(cbC2U(curr->Value()));
1240  #endif
1241  if (c < _T('A') || c > _T('Z')) // first char must be a letter, uppercase letters are key names
1242  ret.Add(cbC2U(curr->Value()));
1243  }
1244  }
1245  return ret;
1246 }
1247 
1249 {
1250  if (doc->ErrorId())
1251  {
1252  cbMessageBox(wxString(_T("### TinyXML error:\n")) << cbC2U(doc->ErrorDesc()));
1253  doc->ClearError();
1254  }
1255 
1256  wxString path(thePath);
1257  to_lower(path);
1258 
1259  Collapse(path);
1260 
1261  wxString illegal(_T(" :.,;!\"\'$%&()[]<>{}?*+-|#"));
1262  size_t i;
1263  while ((i = path.find_first_of(illegal)) != wxString::npos)
1264  path[i] = _T('_');
1265 
1266  if (path.Last() == _T('/'))
1267  path.RemoveLast();
1268 
1269  if (path.IsSameAs(_T("/"))) // this function will refuse to remove root!
1270  return;
1271 
1272  TiXmlElement* parent = pathNode ? pathNode : root;
1273 
1274  if (path.find(_T('/')) != wxString::npos)
1275  {
1276  wxString sub;
1277  do
1278  {
1279  sub = path.BeforeFirst(_T('/'));
1280  path = path.AfterFirst(_T('/'));
1281 
1282  if (sub.IsEmpty())
1283  parent = root;
1284  else if (sub.IsSameAs(_T(".")))
1285  ;
1286  else if (parent != root && sub.IsSameAs(_T("..")))
1287  parent = parent->Parent()->ToElement();
1288  else
1289  {
1290  TiXmlElement* n = parent->FirstChildElement(cbU2C(sub));
1291  if (n)
1292  parent = n;
1293  else
1294  return;
1295  }
1296  }
1297  while (path.find(_T('/')) != wxString::npos);
1298  }
1299 
1300  if (!path.IsEmpty())
1301  {
1302  if (TiXmlNode *toRemove = parent->FirstChild(cbU2C(path)))
1303  {
1304  toRemove->Clear();
1305  parent->RemoveChild(toRemove);
1306  }
1307  }
1308 }
1309 
1310 
1312 {
1313  wxString key(path + _T('/')); // the trailing slash hack is required because AssertPath expects a key name
1314  TiXmlNode* e = AssertPath(key);
1315  wxArrayString ret;
1316 
1317  TiXmlElement *curr = nullptr;
1318  if (e)
1319  {
1320  while (e->IterateChildren(curr) && (curr = e->IterateChildren(curr)->ToElement()))
1321  {
1322  #if wxCHECK_VERSION(3, 0, 0)
1323  wxUniChar c = cbC2U(curr->Value())[0];
1324  #else
1325  wxChar c = *(cbC2U(curr->Value()));
1326  #endif
1327  if (c >= _T('A') && c <= _T('Z')) // opposite of the above
1328  ret.Add(cbC2U(curr->Value()));
1329  }
1330  }
1331  return ret;
1332 }
1333 
1334 void ConfigManager::Write(const wxString& name, const ISerializable& object)
1335 {
1336  wxString key(name);
1337  TiXmlElement* e = AssertPath(key);
1338 
1339  TiXmlElement *obj = GetUniqElement(e, key);
1340 
1341  TiXmlElement *s = GetUniqElement(obj, _T("obj"));
1342  SetNodeText(s, TiXmlText(cbU2C(wxBase64::Encode(object.SerializeOut()))));
1343 }
1344 
1345 bool ConfigManager::Read(const wxString& name, ISerializable* object)
1346 {
1347  wxString str;
1348  wxString key(name);
1349  TiXmlElement* e = AssertPath(key);
1350 
1351  TiXmlHandle parentHandle(e);
1352  TiXmlText *t = (TiXmlText *) parentHandle.FirstChild(cbU2C(key)).FirstChild("obj").FirstChild().Node();
1353 
1354  if (t)
1355  {
1356  str.assign(cbC2U(t->Value()));
1357  object->SerializeIn(wxBase64::Decode(str));
1358  }
1359  return wxEmptyString;
1360 }
1361 
1363 {
1364  wxString key(name);
1365  TiXmlElement* e = AssertPath(key);
1366 
1367  TiXmlElement *leaf = GetUniqElement(e, key);
1368 
1369  TiXmlElement *mNode;
1370  mNode = GetUniqElement(leaf, _T("ssmap"));
1371  leaf->RemoveChild(mNode);
1372  mNode = GetUniqElement(leaf, _T("ssmap"));
1373 
1374  for (ConfigManagerContainer::StringToStringMap::const_iterator it = map.begin(); it != map.end(); ++it)
1375  {
1376  TiXmlElement s(cbU2C(it->first));
1377 
1378  TiXmlText t(cbU2C(it->second));
1379  t.SetCDATA(true);
1380 
1381  s.InsertEndChild(t);
1382  mNode->InsertEndChild(s);
1383  }
1384 }
1385 
1387 {
1388  wxString key(name);
1389  TiXmlElement* e = AssertPath(key);
1390 
1391  TiXmlHandle parentHandle(e);
1392  TiXmlNode *mNode = parentHandle.FirstChild(cbU2C(key)).FirstChild("ssmap").Node();
1393 
1394  TiXmlNode *curr = nullptr;
1395  if (mNode)
1396  {
1397  while ((curr = mNode->IterateChildren(curr)))
1398  (*map)[cbC2U(curr->Value())] = cbC2U(curr->FirstChild()->ToText()->Value());
1399  }
1400 }
1401 
1403 {
1405  Read(name, &ret);
1406  return ret;
1407 }
1408 
1410 {
1411  wxString key(name);
1412  TiXmlElement* e = AssertPath(key);
1413 
1414  TiXmlElement *leaf = GetUniqElement(e, key);
1415 
1416  TiXmlElement *mNode;
1417  mNode = GetUniqElement(leaf, _T("ismap"));
1418  leaf->RemoveChild(mNode);
1419  mNode = GetUniqElement(leaf, _T("ismap"));
1420 
1421  wxString tmp;
1422  for (ConfigManagerContainer::IntToStringMap::const_iterator it = map.begin(); it != map.end(); ++it)
1423  {
1424  tmp.Printf(_T("x%d"), (int) it->first);
1425  TiXmlElement s(tmp.mb_str());
1426 
1427  TiXmlText t(cbU2C(it->second));
1428  t.SetCDATA(true);
1429 
1430  s.InsertEndChild(t);
1431  mNode->InsertEndChild(s);
1432  }
1433 }
1434 
1436 {
1437  wxString key(name);
1438  TiXmlElement* e = AssertPath(key);
1439 
1440  TiXmlHandle parentHandle(e);
1441  TiXmlNode *mNode = parentHandle.FirstChild(cbU2C(key)).FirstChild("ismap").Node();
1442 
1443  TiXmlNode *curr = nullptr;
1444  long tmp;
1445  if (mNode)
1446  {
1447  while ((curr = mNode->IterateChildren(curr)))
1448  {
1449  cbC2U(curr->Value()).Mid(1).ToLong(&tmp);
1450  (*map)[tmp] = cbC2U(curr->FirstChild()->ToText()->Value());
1451  }
1452  }
1453 }
1454 
1456 {
1458  Read(name, &ret);
1459  return ret;
1460 }
1461 
1462 
1463 
1464 
1465 
1466 
1468 {
1469  wxString key(name);
1470  TiXmlElement* e = AssertPath(key);
1471 
1472  TiXmlElement *leaf = GetUniqElement(e, key);
1473 
1474  TiXmlElement *mNode;
1475  mNode = GetUniqElement(leaf, _T("sset"));
1476  leaf->RemoveChild(mNode);
1477  mNode = GetUniqElement(leaf, _T("sset"));
1478 
1479  for (ConfigManagerContainer::StringSet::const_iterator it = set.begin(); it != set.end(); ++it)
1480  {
1481  TiXmlElement s("s");
1482 
1483  TiXmlText t(cbU2C(*it));
1484  t.SetCDATA(true);
1485 
1486  s.InsertEndChild(t);
1487  mNode->InsertEndChild(s);
1488  }
1489 }
1490 
1491 
1493 {
1494  wxString key(name);
1495  TiXmlElement* e = AssertPath(key);
1496 
1497  TiXmlHandle parentHandle(e);
1498  TiXmlNode *mNode = parentHandle.FirstChild(cbU2C(key)).FirstChild("sset").Node();
1499 
1500  TiXmlNode *curr = nullptr;
1501  if (mNode)
1502  {
1503  while ((curr = mNode->IterateChildren(curr)))
1504  set->insert(cbC2U(curr->FirstChild()->ToText()->Value()));
1505  }
1506 }
1507 
1509 {
1511  Read(name, &ret);
1512  return ret;
1513 }
1514 
1515 
1517 {
1518  wxString key(name);
1519  TiXmlElement* e = AssertPath(key);
1520 
1521  TiXmlElement *leaf = GetUniqElement(e, key);
1522 
1523  TiXmlElement *mNode;
1524  mNode = GetUniqElement(leaf, _T("objmap"));
1525  leaf->RemoveChild(mNode);
1526  mNode = GetUniqElement(leaf, _T("objmap"));
1527 
1528  for (ConfigManagerContainer::SerializableObjectMap::const_iterator it = map->begin(); it != map->end(); ++it)
1529  {
1530  TiXmlElement s(cbU2C(it->first));
1531  s.InsertEndChild(TiXmlText(cbU2C(wxBase64::Encode(it->second->SerializeOut()))));
1532  mNode->InsertEndChild(s);
1533  }
1534 }
1535 
1536 
1538 {
1539  ConfigManager::config_folder = ConfigManager::GetUserDataFolder();
1540  ConfigManager::home_folder = wxStandardPathsBase::Get().GetUserConfigDir();
1541  ConfigManager::app_path = ::DetermineExecutablePath();
1542  wxString res_path = ::DetermineResourcesPath();
1543 
1544  // if non-empty, the app has overriden it (e.g. "--prefix" was passed in the command line)
1545  if (data_path_global.IsEmpty())
1546  {
1547  if (platform::windows)
1548  ConfigManager::data_path_global = app_path + _T("\\share\\codeblocks");
1549  else if (platform::macosx)
1550  ConfigManager::data_path_global = res_path + _T("/share/codeblocks");
1551  else
1552  ConfigManager::data_path_global = wxStandardPathsBase::Get().GetDataDir();
1553  }
1554  else
1555  ConfigManager::data_path_global = UnixFilename(data_path_global);
1556 
1557 #ifdef CB_AUTOCONF
1558  if (plugin_path_global.IsEmpty())
1559  {
1560  if (platform::windows)
1561  ConfigManager::plugin_path_global = data_path_global;
1562  else if (platform::macosx)
1563  ConfigManager::plugin_path_global = data_path_global + _T("/plugins");
1564  else
1565  {
1566 #ifdef __WXGTK__
1567  // It seems we can not longer rely on wxStandardPathsBase::Get().GetPluginsDir(),
1568  // because its behaviour has changed on some systems (at least Fedora 14 64-bit).
1569  // So we create the pathname manually
1570  ConfigManager::plugin_path_global = ((const wxStandardPaths&)wxStandardPaths::Get()).GetInstallPrefix() + _T("/lib/codeblocks/plugins");
1571  // first assume, we use standard-paths
1572  if (!wxDirExists(ConfigManager::plugin_path_global) && wxIsPlatform64Bit())
1573  {
1574  // if standard-path does not exist and we are on 64-bit system, use lib64 instead
1575  ConfigManager::plugin_path_global = ((const wxStandardPaths&)wxStandardPaths::Get()).GetInstallPrefix() + _T("/lib64/codeblocks/plugins");
1576  }
1577 #endif // __WXGTK__
1578  }
1579  }
1580 #endif
1581 
1582  wxString dataPathUser = ConfigManager::config_folder + wxFILE_SEP_PATH + _T("share");
1583 #ifdef __linux__
1585  dataPathUser = wxString::FromUTF8(g_build_filename (g_get_user_data_dir(), NULL));
1586 #endif // __linux__
1587 
1588  ConfigManager::data_path_user = dataPathUser + wxFILE_SEP_PATH + _T("codeblocks");
1589 
1590  // if user- and global-datapath are the same (can happen in portable mode) we run in conflicts
1591  // so we extend the user-datapath with the users name
1592  if (wxFileName(ConfigManager::data_path_user) == wxFileName(ConfigManager::data_path_global))
1593  ConfigManager::data_path_user.append(_(".")+wxGetUserId());
1594 
1595  CreateDirRecursively(ConfigManager::config_folder);
1596  CreateDirRecursively(ConfigManager::data_path_user + _T("/plugins/"));
1597  CreateDir(ConfigManager::data_path_user + _T("/scripts/"));
1598 
1599  ConfigManager::temp_folder = wxStandardPathsBase::Get().GetTempDir();
1600 }
1601 
1603 {
1604 #ifdef __linux__
1605  // if the old config-folder (~/.codeblocks) does not exist, we have nothing to do.
1606  if (!wxDirExists(wxStandardPaths::Get().GetUserDataDir()))
1607  return;
1608 
1609  // ConfigManager::config_folder might be the portable-path but we want to migrate the standard-conform folder,
1610  // but only if it not already exists
1611  wxString newConfigFolder = wxString::FromUTF8(g_build_filename (g_get_user_config_dir(), "codeblocks", NULL));
1612  // if the new config folder already exist, we step out immediately
1613  if (wxDirExists(newConfigFolder))
1614  return;
1615 
1616  wxString oldConfigFolder = wxStandardPaths::Get().GetUserDataDir();
1617  wxString oldDataFolder = oldConfigFolder + wxFILE_SEP_PATH + _T("share") + wxFILE_SEP_PATH + _T("codeblocks");
1618  wxString newDataFolder = wxString::FromUTF8(g_build_filename (g_get_user_data_dir(), NULL)) + wxFILE_SEP_PATH + _T("codeblocks");
1619  wxString msg;
1620  msg = F(_("The places where the configuration files and user-data files are stored\n"
1621  "have been changed to be more standard-conform.\n"
1622  "\n"
1623  "Now moving \"%s\"\n"
1624  "to \"%s\"\n"
1625  "and \"%s\"\n"
1626  "to \"%s\".\n"),
1627  oldDataFolder.wx_str(),
1628  newDataFolder.wx_str(),
1629  oldConfigFolder.wx_str(),
1630  newConfigFolder.wx_str());
1631  cbMessageBox(msg, _("Try to migrate config-folder ..."), wxICON_INFORMATION);
1632 
1633  bool success = true;
1634  if (wxDirExists(oldDataFolder))
1635  {
1636  // make sure the target-folder exists
1637  CreateDirRecursively(newDataFolder);
1638  success = wxRenameFile(oldDataFolder, newDataFolder);
1639  wxRmdir(oldConfigFolder + wxFILE_SEP_PATH + _T("share"));
1640  }
1641  if (success)
1642  {
1643  // make sure the target-folder exists
1644  CreateDirRecursively(newConfigFolder);
1645  success = wxRenameFile(oldConfigFolder, newConfigFolder);
1646  }
1647  if (!success)
1648  {
1649  msg = F(_("Error moving \"%s\"\n"
1650  "to \"%s\"\n"
1651  "or \"%s\"\n"
1652  "to \"%s\".\n\n"
1653  "Please check the folders manually (access rights?) !\n"
1654  "A new configuration will be created from scratch!"),
1655  oldDataFolder.wx_str(),
1656  newDataFolder.wx_str(),
1657  oldConfigFolder.wx_str(),
1658  newConfigFolder.wx_str());
1659  cbMessageBox(msg, _("Error migrating config-folder ..."), wxICON_ERROR);
1660  }
1661 #endif // __linux__
1662 }
1663 
1664 void ConfigManagerWrapper::Write(const wxString& name, const wxString& value, bool ignoreEmpty)
1665 {
1666  if (m_namespace.empty())
1667  return;
1668  ConfigManager *c = Manager::Get()->GetConfigManager(m_namespace);
1669  c->Write(m_basepath + name, value, ignoreEmpty);
1670 }
1671 
1673 {
1674  if (m_namespace.empty())
1675  return defaultVal;
1676  ConfigManager *c = Manager::Get()->GetConfigManager(m_namespace);
1677  return c->Read(m_basepath + key, defaultVal);
1678 }
1679 
1681 {
1682  if (m_namespace.empty())
1683  return false;
1684  ConfigManager *c = Manager::Get()->GetConfigManager(m_namespace);
1685  return c->Read(key, str);
1686 }
1687 void ConfigManagerWrapper::Write(const wxString& key, const char* str)
1688 {
1689  if (m_namespace.empty())
1690  return;
1691  ConfigManager *c = Manager::Get()->GetConfigManager(m_namespace);
1692  c->Write(key, str);
1693 }
1694 
1695 void ConfigManagerWrapper::Write(const wxString& name, int value)
1696 {
1697  if (m_namespace.empty())
1698  return;
1699  ConfigManager *c = Manager::Get()->GetConfigManager(m_namespace);
1700  c->Write(m_basepath + name, value);
1701 }
1702 bool ConfigManagerWrapper::Read(const wxString& name, int* value)
1703 {
1704  if (m_namespace.empty())
1705  return false;
1706  ConfigManager *c = Manager::Get()->GetConfigManager(m_namespace);
1707  return c->Read(m_basepath + name, value);
1708 }
1709 
1710 int ConfigManagerWrapper::ReadInt(const wxString& name, int defaultVal)
1711 {
1712  if (m_namespace.empty())
1713  return defaultVal;
1714  ConfigManager *c = Manager::Get()->GetConfigManager(m_namespace);
1715  return c->ReadInt(m_basepath + name, defaultVal);
1716 }
1717 
1718 void ConfigManagerWrapper::Write(const wxString& name, bool value)
1719 {
1720  if (m_namespace.empty())
1721  return;
1722  ConfigManager *c = Manager::Get()->GetConfigManager(m_namespace);
1723  c->Write(m_basepath + name, value);
1724 }
1725 bool ConfigManagerWrapper::Read(const wxString& name, bool* value)
1726 {
1727  if (m_namespace.empty())
1728  return false;
1729  ConfigManager *c = Manager::Get()->GetConfigManager(m_namespace);
1730  return c->Read(m_basepath + name, value);
1731 }
1732 bool ConfigManagerWrapper::ReadBool(const wxString& name, bool defaultVal)
1733 {
1734  if (m_namespace.empty())
1735  return defaultVal;
1736  ConfigManager *c = Manager::Get()->GetConfigManager(m_namespace);
1737  return c->ReadBool(m_basepath + name, defaultVal);
1738 }
1739 
1740 void ConfigManagerWrapper::Write(const wxString& name, double value)
1741 {
1742  if (m_namespace.empty())
1743  return;
1744  ConfigManager *c = Manager::Get()->GetConfigManager(m_namespace);
1745  c->Write(m_basepath + name, value);
1746 }
1747 bool ConfigManagerWrapper::Read(const wxString& name, double* value)
1748 {
1749  if (m_namespace.empty())
1750  return false;
1751  ConfigManager *c = Manager::Get()->GetConfigManager(m_namespace);
1752  return c->Read(m_basepath + name, value);
1753 }
1754 double ConfigManagerWrapper::ReadDouble(const wxString& name, double defaultVal)
1755 {
1756  if (m_namespace.empty())
1757  return defaultVal;
1758  ConfigManager *c = Manager::Get()->GetConfigManager(m_namespace);
1759  return c->ReadDouble(m_basepath + name, defaultVal);
1760 }
1761 
1763 {
1764  if (platform::windows)
1765  return wxT("compiler.dll");
1766  else if (platform::darwin || platform::macosx)
1767  return wxT("libcompiler.dylib");
1768  else
1769  return wxT("libcompiler.so");
1770 }
1771 
1773 {
1774  ConfigManager *bbcfg = Manager::Get()->GetConfigManager(_T("plugins"));
1775  wxArrayString bbplugins = bbcfg->ReadArrayString(_T("/batch_build_plugins"));
1776 
1777  if (!bbplugins.GetCount())
1778  bbplugins.Add(getCompilerPluginFilename());
1779 
1780  return bbplugins;
1781 }
1782 
1783 void cbWriteBatchBuildPlugins(wxArrayString bbplugins, wxWindow *messageBoxParent)
1784 {
1785  const wxString &compiler = getCompilerPluginFilename();
1786 
1787  if (bbplugins.Index(compiler) == wxNOT_FOUND)
1788  {
1789  bbplugins.Add(compiler);
1790  cbMessageBox(_("The compiler plugin must always be loaded for batch builds!\n"
1791  "Automatically re-enabled."),
1792  _("Warning"), wxICON_WARNING, messageBoxParent);
1793  }
1794  ConfigManager *bbcfg = Manager::Get()->GetConfigManager(_T("plugins"));
1795  bbcfg->Write(_T("/batch_build_plugins"), bbplugins);
1796 }
wxString F(const wxChar *msg,...)
sprintf-like function
Definition: logmanager.h:20
bool wxRmdir(const wxString &dir, int flags=0)
const wxString data_path(_T("data_path"))
bool wxRenameFile(const wxString &file1, const wxString &file2, bool overwrite=true)
static wxString GetFolder(SearchDirs dir)
Access one of Code::Blocks&#39; folders.
Data folder in user&#39;s dir.
Definition: configmanager.h:75
wxString Read(const wxString &key, const wxString &defaultVal=wxEmptyString)
wxString ReadBinary(const wxString &name)
TiXmlDocument * volatile_doc
#define wxICON_WARNING
static void InitPaths()
wxString cfg
const int version
ConfigManager * Build(const wxString &name_space)
ConfigManager * GetConfigManager(const wxString &name_space) const
Definition: manager.cpp:474
int ReadInt(const wxString &name, int defaultVal=0)
static Manager * Get()
Use Manager::Get() to get a pointer to its instance Manager::Get() is guaranteed to never return an i...
Definition: manager.cpp:182
#define wxNO
static wxString app_path
void to_lower(wxString &s)
void Write(const wxString &name, const wxString &value, bool ignoreEmpty=false)
TiXmlDocument * doc
virtual int ShowModal()
size_t length() const
static wxString GetUserDataFolder()
ConfigManagerContainer::StringToStringMap ReadSSMap(const wxString &name)
#define wxICON_ERROR
bool wxFileExists(const wxString &filename)
virtual unsigned char Red() const
static wxStandardPaths & Get()
Scripts folder in base dir.
Definition: configmanager.h:80
wxColour wxNullColour
static unsigned int GetRevisionNumber()
ConfigManager(TiXmlElement *r)
bool ReadBool(const wxString &name, bool defaultVal=false)
TiXmlElement * pathNode
int Index(const wxString &sz, bool bCase=true, bool bFromEnd=false) const
ConfigManagerContainer::IntToStringMap ReadISMap(const wxString &name)
wxColour ReadColour(const wxString &name, const wxColour &defaultVal= *wxBLACK)
Scripts folder in user&#39;s dir.
Definition: configmanager.h:74
const wxString app_path(_T("app_path"))
void SetPath(const wxString &strPath)
wxCStrData c_str() const
bool ReadBool(const wxString &name, bool defaultVal=false)
bool wxDirExists(const wxString &dirname)
TiXmlElement * AssertPath(wxString &path)
static CfgMgrBldr * Get()
Definition: manager.h:199
wxString & append(const wxString &str, size_t pos, size_t n)
#define wxNO_DEFAULT
#define _T(string)
Convenience value meaning "all sd*Global values".
Definition: configmanager.h:83
static wxString temp_folder
TiXmlElement * GetUniqElement(TiXmlElement *p, const wxString &q)
bool LoadDocument(const wxString &filename, TiXmlDocument *doc)
Definition: tinywxuni.cpp:13
const wxCharBuffer mb_str(const wxMBConv &conv=wxConvLibc) const
Config folder.
Definition: configmanager.h:70
static ConfigManager * GetConfigManager(const wxString &name_space)
#define wxICON_INFORMATION
~CfgMgrBldr() override
All dirs in the PATH environment variable.
Definition: configmanager.h:69
wxString DetermineExecutablePath()
wxString AfterFirst(wxUniChar ch) const
#define wxT(string)
#define wxNOT_FOUND
wxURLError GetError() const
int ReadInt(const wxString &name, int defaultVal=0)
wxArrayString ReadArrayString(const wxString &name)
size_t find(const wxString &str, size_t nStart=0) const
void Set(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha=wxALPHA_OPAQUE)
static wxString LocateDataFile(const wxString &filename, int search_dirs=sdAllKnown)
Locate a file in an installation- and platform-independent way.
DLLIMPORT const wxWX2MBbuf cbU2C(const wxString &str)
Return multibyte (C string) representation of the string.
Definition: globals.cpp:743
void Set(const wxString &name)
static bool has_alternate_user_data_path
wxUSE_UNICODE_dependent wxChar
void UnSet(const wxString &name)
static wxString alternate_user_data_path
wxString BeforeFirst(wxUniChar ch, wxString *rest=NULL) const
bool Contains(const wxString &str) const
void Write(const wxString &name, const wxString &value, bool ignoreEmpty=false)
DLLIMPORT wxString UnixFilename(const wxString &filename, wxPathFormat format=wxPATH_NATIVE)
Definition: globals.cpp:228
User&#39;s home directory.
Definition: configmanager.h:66
NamespaceMap namespaces
size_t find_first_of(const char *sz, size_t nStart=0) const
wxString & RemoveLast(size_t n=1)
static wxString config_folder
null_pointer_t nullptr
Definition: nullptr.cpp:16
TiXmlDocument * doc
Definition: configmanager.h:99
void Collapse(wxString &str) const
static wxString GetConfigFolder()
wxArrayString EnumerateSubPaths(const wxString &path)
DLLIMPORT wxString cbC2U(const char *str)
Return str as a proper unicode-compatible string.
Definition: globals.cpp:733
void Empty()
DLLIMPORT wxUint32 FromString(const wxString &text)
Definition: crc32.cpp:64
static wxString FromUTF8(const char *s)
bool Exists(const wxString &name)
bool Alloc(size_t nLen)
DLLIMPORT wxString Encode(const wxUint8 *pData, size_t len)
Definition: base64.cpp:48
DLLIMPORT bool CreateDir(const wxString &full_path, int perms=0755)
Definition: globals.cpp:631
Convenience value meaning "all sd*User values".
Definition: configmanager.h:77
virtual unsigned char Green() const
wxInputStream * GetInputStream()
wxUSE_UNICODE_WCHAR_dependent wxStringCharType
bool IsSameAs(const wxString &s, bool caseSensitive=true) const
LogManager * GetLogManager() const
Definition: manager.cpp:439
static wxFileName DirName(const wxString &dir, wxPathFormat format=wxPATH_NATIVE)
wxString & Truncate(size_t len)
wxString Read(const wxString &key, const wxString &defaultVal=wxEmptyString)
wxArtID wxART_ERROR
const wxStringCharType * wx_str() const
virtual unsigned char Blue() const
static wxFontEncoding GetSystemEncoding()
bool Add(const wxString &path)
void cbWriteBatchBuildPlugins(wxArrayString bbplugins, wxWindow *messageBoxParent)
Write the list of batch build plugins in the config.
wxString FindConfigFile(const wxString &filename)
wxString wxEmptyString
wxString & assign(const wxString &str, size_t pos, size_t n)
wxCriticalSection cs
void SetProxy(const wxString &url_proxy)
double ReadDouble(const wxString &name, double defaultVal=0.0f)
#define wxSTAY_ON_TOP
std::set< wxString > StringSet
Definition: configmanager.h:56
Current working folder.
Definition: configmanager.h:71
Definition: manager.h:183
All known dirs (i.e. all of the above)
Definition: configmanager.h:85
const wxString & _(const wxString &string)
virtual ~ISerializable()
#define cbThrow(message)
Definition: cbexception.h:42
Plugins folder in user&#39;s dir.
Definition: configmanager.h:73
Plugins folder in base dir.
Definition: configmanager.h:79
virtual bool SetYesNoLabels(const ButtonLabel &yes, const ButtonLabel &no)
void SwitchTo(const wxString &absFN)
bool ToLong(long *val, int base=10) const
Code::Blocks&#39; installation base.
Definition: configmanager.h:67
static wxString data_path_global
static wxString GetProxy()
DLLIMPORT wxString Decode(const wxString &data)
Definition: base64.cpp:91
wxString FindValidPath(const wxString &file) const
void DeleteSubPath(const wxString &strPath)
bool IsEmpty() const
DLLIMPORT void PlaceWindow(wxTopLevelWindow *w, cbPlaceDialogMode mode=pdlBest, bool enforce=false)
Definition: globals.cpp:1177
wxString GetPath(int flags=wxPATH_GET_VOLUME, wxPathFormat format=wxPATH_NATIVE) const
static bool SetUserDataFolder(const wxString &user_data_path)
static const size_t npos
void UngetWriteBuf()
const wxString dotDot(_T(".."))
wxString GetPath() const
void DebugLog(const wxString &msg, Logger::level lv=Logger::info)
Definition: logmanager.h:146
static void MigrateFolders()
static void handleConfigError(TiXmlDocument &doc, const wxString &fileName, const wxString &additionalMessage)
Print error message an allow the user to either discard the old config or close the application...
static wxString data_path_user
TiXmlElement * root
wxString & Prepend(const wxString &str)
#define wxYES
static wxString getCompilerPluginFilename()
size_t Add(const wxString &str, size_t copies=1)
SearchDirs
Search dirs values.
Definition: configmanager.h:64
const wxString ptr(_T("*"))
bool StartsWith(const wxString &prefix, wxString *rest=NULL) const
bool SaveDocument(const wxString &, TiXmlDocument *)
Definition: tinywxuni.cpp:45
size_t GetCount() const
wxUniChar GetChar(size_t n) const
wxUniChar Last() const
virtual wxString GetUserDataDir() const
ConfigManagerContainer::StringSet ReadSSet(const wxString &name)
DLLIMPORT bool CreateDirRecursively(const wxString &full_path, int perms=0755)
Definition: globals.cpp:610
void to_upper(wxString &s)
Data folder in base dir.
Definition: configmanager.h:81
static wxString home_folder
void SwitchToR(const wxString &absFN)
wxString wxGetUserId()
friend class ConfigManager
System-wide temp folder.
Definition: configmanager.h:68
int Printf(const wxString &pszFormat,...)
void AddEnvList(const wxString &env_variable)
wxArrayString cbReadBatchBuildPlugins()
Read the list of batch build plugins and return them.
wxString GetFullPath(wxPathFormat format=wxPATH_NATIVE) const
wxArrayString EnumerateKeys(const wxString &path)
#define NULL
Definition: prefix.cpp:59
std::map< wxString, ISerializable * > SerializableObjectMap
Definition: configmanager.h:58
static wxString Format(const wxString &format,...)
wxString Mid(size_t first, size_t nCount=wxString::npos) const
Dialog that contains a "Don&#39;t annoy me" checkbox.
double ReadDouble(const wxString &name, double defaultVal=0.0f)
DLLIMPORT int cbMessageBox(const wxString &message, const wxString &caption=wxEmptyString, int style=wxOK, wxWindow *parent=NULL, int x=-1, int y=-1)
wxMessageBox wrapper.
Definition: globals.cpp:1395
wxString InvalidNameMessage(const wxString &what, const wxString &sub, TiXmlElement *localPath) const
void SetNodeText(TiXmlElement *n, const TiXmlText &t)
void WriteBinary(const wxString &name, const wxString &source)
wxString wxGetCwd()
bool wxIsPlatform64Bit()
wxStringCharType * GetWriteBuf(size_t len)
DLLIMPORT wxString realpath(const wxString &path)
Definition: globals.cpp:1348
std::map< int, wxString > IntToStringMap
Definition: configmanager.h:55
std::map< wxString, wxString > StringToStringMap
Definition: configmanager.h:54