~ubuntu-branches/ubuntu/raring/codeblocks/raring-proposed

« back to all changes in this revision

Viewing changes to .pc/01_codeblocks_plugin_path.patch/src/sdk/configmanager.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cosme Domínguez Díaz
  • Date: 2010-08-09 04:38:38 UTC
  • mfrom: (1.1.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20100809043838-a59ygguym4eg0jgw
Tags: 10.05-0ubuntu1
* New upstream release. Closes (LP: #322350)
 - Switch to dpkg-source 3.0 (quilt) format
 - Remove unneeded README.source
 - Add debian/get-source-orig script that removes all
   Windows prebuilt binaries
* Bump Standards-Version to 3.9.1
 - Stop shipping *.la files
* debian/control
 - Add cdbs package as Build-Depend
 - Add libbz2-dev and zlib1g-dev packages as
   Build-Depends (needed by libhelp_plugin.so)
 - Remove dpatch package of Build-Depends
 - Add codeblocks-contrib-debug package
 - Split architecture-independent files of codeblocks
   package in codeblocks-common package
* debian/rules
 - Switch to CDBS rules system
 - Add parallel build support
 - Add a call to debian/get-source-orig script
 - Use lzma compression (saves 23,5 MB of free space)
* debian/patches
 - Refresh 01_codeblocks_plugin_path
 - Add 02_no_Makefiles_in_debian_dir to remove any link
   in codeblocks build system to deleted Makefiles of debian directory
 - Drop 02_ftbfs_gcc44 and 03_ftbfs_glib221 (merged in upstream)
* debian/watch
 - Update to use the new host (berlios.de)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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: 6014 $
 
6
 * $Id: configmanager.cpp 6014 2009-12-31 21:44:01Z jenslody $
 
7
 * $HeadURL: svn+ssh://jenslody@svn.berlios.de/svnroot/repos/codeblocks/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
 
 
29
#ifdef __WXMSW__
 
30
#include <shlobj.h>
 
31
#endif
 
32
 
 
33
#if defined(__APPLE__) && defined(__MACH__)
 
34
#include <sys/param.h>
 
35
#include <mach-o/dyld.h>
 
36
#endif
 
37
 
 
38
#ifdef __WXMAC__
 
39
#include "wx/mac/corefoundation/cfstring.h"
 
40
#include "wx/intl.h"
 
41
 
 
42
#include <CoreFoundation/CFBundle.h>
 
43
#include <CoreFoundation/CFURL.h>
 
44
#endif
 
45
 
 
46
#include "tinyxml/tinywxuni.h"
 
47
#include <stdlib.h>
 
48
 
 
49
template<> CfgMgrBldr* Mgr<CfgMgrBldr>::instance = 0;
 
50
template<> bool  Mgr<CfgMgrBldr>::isShutdown = false;
 
51
 
 
52
wxString ConfigManager::config_folder;
 
53
wxString ConfigManager::home_folder;
 
54
wxString ConfigManager::data_path_user;
 
55
wxString ConfigManager::data_path_global;
 
56
#ifdef CB_AUTOCONF
 
57
wxString ConfigManager::plugin_path_global;
 
58
#endif
 
59
wxString ConfigManager::app_path;
 
60
wxString ConfigManager::temp_folder;
 
61
bool ConfigManager::relo = 0;
 
62
 
 
63
#ifdef __WINDOWS__
 
64
wxString GetPortableConfigDir()
 
65
{
 
66
    DWORD bufLen = 32780;
 
67
    TCHAR buffer[32780];
 
68
    int ret = GetEnvironmentVariable(_T("APPDATA"), buffer, bufLen);
 
69
    if (ret == 0)
 
70
    {
 
71
        return wxStandardPathsBase::Get().GetUserDataDir();
 
72
    }
 
73
    else
 
74
    {
 
75
        return wxString::Format(_T("%s\\codeblocks"), buffer);
 
76
    }
 
77
}
 
78
#endif
 
79
 
 
80
namespace CfgMgrConsts
 
81
{
 
82
    const wxString app_path(_T("app_path"));
 
83
    const wxString data_path(_T("data_path"));
 
84
    const wxString dotDot(_T(".."));
 
85
    const int version = 1;
 
86
}
 
87
 
 
88
 
 
89
namespace
 
90
{
 
91
    wxString DetermineExecutablePath()
 
92
    {
 
93
        #if (__WXMSW__)
 
94
            wxChar name[MAX_PATH];
 
95
            GetModuleFileName(0L, name, MAX_PATH);
 
96
            wxFileName fname(name);
 
97
            return fname.GetPath(wxPATH_GET_VOLUME);
 
98
        #else
 
99
        #if (__linux__)
 
100
            char c[PATH_MAX+1];
 
101
            char *p = realpath("/proc/self/exe", &c[0]);
 
102
            if(p == 0)
 
103
                return _T(".");
 
104
            wxFileName fname(cbC2U(p));
 
105
            return fname.GetPath(wxPATH_GET_VOLUME);
 
106
        #elif defined(sun) || defined(__sun)
 
107
            wxFileName fname(cbC2U(getexecname()));
 
108
            return fname.GetPath(wxPATH_GET_VOLUME);
 
109
        #elif defined(__APPLE__) && defined(__MACH__)
 
110
            char path[MAXPATHLEN+1];
 
111
            uint32_t path_len = MAXPATHLEN;
 
112
            // SPI first appeared in Mac OS X 10.2
 
113
            _NSGetExecutablePath(path, &path_len);
 
114
            wxFileName fname(wxString(path, wxConvUTF8));
 
115
            return fname.GetPath(wxPATH_GET_VOLUME);
 
116
        #else
 
117
            return _T(".");
 
118
        #endif
 
119
        #endif
 
120
    };
 
121
 
 
122
    wxString DetermineResourcesPath()
 
123
    {
 
124
        #if defined(__WXMAC__)
 
125
            CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
 
126
            CFURLRef absoluteURL = CFURLCopyAbsoluteURL(resourcesURL); // relative -> absolute
 
127
            CFRelease(resourcesURL);
 
128
            CFStringRef cfStrPath = CFURLCopyFileSystemPath(absoluteURL,kCFURLPOSIXPathStyle);
 
129
            CFRelease(absoluteURL);
 
130
            wxString str = wxMacCFStringHolder(cfStrPath).AsString(wxLocale::GetSystemEncoding());
 
131
            if (!str.Contains(wxString(_T("/Resources"))))
 
132
               return ::DetermineExecutablePath() + _T("/.."); // not a bundle, use relative path
 
133
            return str;
 
134
        #else
 
135
            return _T(".");
 
136
        #endif
 
137
    };
 
138
};
 
139
 
 
140
 
 
141
inline void ConfigManager::Collapse(wxString& str) const
 
142
{
 
143
    const wxChar *src = str.c_str();
 
144
    wxChar *dst = (wxChar*) src;
 
145
    wxChar c;
 
146
    size_t len = 0;
 
147
 
 
148
    while((c = *src))
 
149
    {
 
150
        ++src;
 
151
 
 
152
        *dst = c;
 
153
        ++dst;
 
154
        ++len;
 
155
 
 
156
        if(c == _T('/'))
 
157
        while(*src == _T('/'))
 
158
            ++src;
 
159
    }
 
160
    str.Truncate(len);
 
161
};
 
162
 
 
163
ISerializable::ISerializable()
 
164
{}
 
165
 
 
166
ISerializable::~ISerializable()
 
167
{}
 
168
 
 
169
 
 
170
 
 
171
 
 
172
/* ------------------------------------------------------------------------------------------------------------------
 
173
*  "Builder pattern" class for ConfigManager
 
174
*  Do not use this class  -  Manager::Get()->GetConfigManager() is a lot friendlier
 
175
*/
 
176
 
 
177
CfgMgrBldr::CfgMgrBldr() : doc(0), volatile_doc(0), r(false)
 
178
{
 
179
    TiXmlBase::SetCondenseWhiteSpace(false);
 
180
    wxString personality(Manager::Get()->GetPersonalityManager()->GetPersonality());
 
181
 
 
182
    if(personality.StartsWith(_T("http://")))
 
183
    {
 
184
        SwitchToR(personality);
 
185
        return;
 
186
    }
 
187
 
 
188
    cfg = FindConfigFile(personality + _T(".conf"));
 
189
 
 
190
    if(cfg.IsEmpty())
 
191
    {
 
192
        #ifdef __WINDOWS__
 
193
        cfg = GetPortableConfigDir() + wxFILE_SEP_PATH + personality + _T(".conf");
 
194
        #else
 
195
        cfg = wxStandardPathsBase::Get().GetUserDataDir() + wxFILE_SEP_PATH + personality + _T(".conf");
 
196
        #endif
 
197
        doc = new TiXmlDocument();
 
198
        doc->InsertEndChild(TiXmlDeclaration("1.0", "UTF-8", "yes"));
 
199
        doc->InsertEndChild(TiXmlElement("CodeBlocksConfig"));
 
200
        doc->FirstChildElement("CodeBlocksConfig")->SetAttribute("version", CfgMgrConsts::version);
 
201
        return;
 
202
    }
 
203
    SwitchTo(cfg);
 
204
}
 
205
 
 
206
 
 
207
wxString CfgMgrBldr::FindConfigFile(const wxString& filename)
 
208
{
 
209
    wxPathList searchPaths;
 
210
 
 
211
#ifdef __WINDOWS__
 
212
    wxString u(GetPortableConfigDir() + wxFILE_SEP_PATH + filename);
 
213
#else
 
214
    wxString u(wxStandardPathsBase::Get().GetUserDataDir() + wxFILE_SEP_PATH + filename);
 
215
#endif
 
216
    wxString e(::DetermineExecutablePath() + wxFILE_SEP_PATH +filename);
 
217
 
 
218
    if(::wxFileExists(u))
 
219
    {
 
220
        return u;
 
221
    }
 
222
    if(::wxFileExists(e))
 
223
    {
 
224
        ConfigManager::relo = true;
 
225
        return e;
 
226
    }
 
227
    return wxEmptyString;
 
228
}
 
229
 
 
230
 
 
231
void CfgMgrBldr::SwitchTo(const wxString& fileName)
 
232
{
 
233
    doc = new TiXmlDocument();
 
234
 
 
235
    if(!TinyXML::LoadDocument(fileName, doc))
 
236
        cbThrow(wxString::Format(_T("Error accessing file:\n%s"), fileName.c_str()));
 
237
 
 
238
    if(doc->ErrorId())
 
239
        cbThrow(wxString::Format(_T("TinyXML error: %s\nIn file: %s\nAt row %d, column: %d."), cbC2U(doc->ErrorDesc()).c_str(), fileName.c_str(), doc->ErrorRow(), doc->ErrorCol()));
 
240
 
 
241
    TiXmlElement* docroot = doc->FirstChildElement("CodeBlocksConfig");
 
242
 
 
243
    if(doc->ErrorId())
 
244
        cbThrow(wxString::Format(_T("TinyXML error: %s\nIn file: %s\nAt row %d, column: %d."), cbC2U(doc->ErrorDesc()).c_str(), fileName.c_str(), doc->ErrorRow(), doc->ErrorCol()));
 
245
 
 
246
    const char *vers = docroot->Attribute("version");
 
247
    if(!vers || atoi(vers) != 1)
 
248
        cbMessageBox(_("ConfigManager encountered an unknown config file version. Continuing happily."), _("Warning"), wxICON_WARNING);
 
249
 
 
250
    doc->ClearError();
 
251
 
 
252
    wxString info;
 
253
#ifndef __GNUC__
 
254
 
 
255
    info.Printf(_T( " application info:\n"
 
256
                    "\t svn_revision:\t%d\n"
 
257
                    "\t build_date:\t%s, %s "), ConfigManager::GetRevisionNumber(), wxT(__DATE__), wxT(__TIME__));
 
258
#else
 
259
 
 
260
    info.Printf(_T( " application info:\n"
 
261
                    "\t svn_revision:\t%d\n"
 
262
                    "\t build_date:\t%s, %s\n"
 
263
                    "\t gcc_version:\t%d.%d.%d "), ConfigManager::GetRevisionNumber(), wxT(__DATE__), wxT(__TIME__),
 
264
                __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
 
265
#endif
 
266
 
 
267
    if(platform::windows)
 
268
        info.append(_T("\n\t Windows "));
 
269
    if(platform::linux)
 
270
        info.append(_T("\n\t Linux "));
 
271
    if(platform::macosx)
 
272
        info.append(_T("\n\t Mac OS X "));
 
273
    if(platform::unix)
 
274
        info.append(_T("\n\t Unix "));
 
275
 
 
276
    info.append(platform::unicode ? _T("Unicode ") : _T("ANSI "));
 
277
 
 
278
    TiXmlComment c;
 
279
    c.SetValue((const char*) info.mb_str());
 
280
 
 
281
    TiXmlNode *firstchild = docroot->FirstChild();
 
282
    if(firstchild && firstchild->ToComment())
 
283
    {
 
284
        docroot->RemoveChild(firstchild);
 
285
        firstchild = docroot->FirstChild();
 
286
    }
 
287
 
 
288
    if(firstchild)
 
289
        docroot->InsertBeforeChild(firstchild, c);
 
290
    else
 
291
        docroot->InsertEndChild(c);
 
292
}
 
293
 
 
294
void CfgMgrBldr::SwitchToR(const wxString& absFileName)
 
295
{
 
296
    if(doc)
 
297
        delete doc;
 
298
    doc = new TiXmlDocument();
 
299
    doc->ClearError();
 
300
 
 
301
    cfg = absFileName;
 
302
 
 
303
    wxURL url(absFileName);
 
304
    url.SetProxy(ConfigManager::GetProxy());
 
305
    if (url.GetError() == wxURL_NOERR)
 
306
    {
 
307
        wxInputStream *is = url.GetInputStream();
 
308
        if (is && is->IsOk())
 
309
        {
 
310
            size_t size = is->GetSize();
 
311
            wxString str;
 
312
            #if wxCHECK_VERSION(2, 9, 0)
 
313
            wxChar* c = wxStringBuffer(str, size);
 
314
            #else
 
315
            wxChar* c = str.GetWriteBuf(size);
 
316
            #endif
 
317
            is->Read(c, size);
 
318
            #if !wxCHECK_VERSION(2, 9, 0)
 
319
            str.UngetWriteBuf(size);
 
320
            #endif
 
321
 
 
322
            doc = new TiXmlDocument();
 
323
 
 
324
            if(doc->Parse(cbU2C(str)))
 
325
            {
 
326
                doc->ClearError();
 
327
                delete is;
 
328
                return;
 
329
            }
 
330
            if(Manager::Get()->GetLogManager())
 
331
            {
 
332
                Manager::Get()->GetLogManager()->DebugLog(_T("##### Error loading or parsing remote config file"));
 
333
                Manager::Get()->GetLogManager()->DebugLog(cbC2U(doc->ErrorDesc()));
 
334
                doc->ClearError();
 
335
            }
 
336
        }
 
337
        delete is;
 
338
    }
 
339
    cfg.Empty();
 
340
    SwitchTo(wxEmptyString); // fall back
 
341
}
 
342
 
 
343
CfgMgrBldr::~CfgMgrBldr()
 
344
{
 
345
    NamespaceMap::iterator it;
 
346
    for( it = namespaces.begin(); it != namespaces.end(); ++it )
 
347
    {
 
348
        delete it->second;
 
349
    }
 
350
    namespaces.clear();
 
351
    Close();
 
352
    delete volatile_doc;
 
353
}
 
354
 
 
355
void CfgMgrBldr::Close()
 
356
{
 
357
    if(doc)
 
358
    {
 
359
        if(!cfg.StartsWith(_T("http://")))
 
360
        {
 
361
            if (!TinyXML::SaveDocument(cfg, doc))
 
362
            {
 
363
                wxSafeShowMessage(_T("Could not save config file..."), _("Warning"));
 
364
                // TODO (thomas#1#): add "retry" option
 
365
            }
 
366
        }
 
367
        else
 
368
        {
 
369
            // implement WebDAV another time
 
370
        }
 
371
        delete doc;
 
372
    }
 
373
    doc = 0;
 
374
}
 
375
 
 
376
 
 
377
ConfigManager* CfgMgrBldr::GetConfigManager(const wxString& name_space)
 
378
{
 
379
    return Get()->Build(name_space);
 
380
}
 
381
 
 
382
 
 
383
ConfigManager* CfgMgrBldr::Build(const wxString& name_space)
 
384
{
 
385
    if(name_space.IsEmpty())
 
386
        cbThrow(_T("You attempted to get a ConfigManager instance without providing a namespace."));
 
387
 
 
388
    wxCriticalSectionLocker locker(cs);
 
389
    NamespaceMap::iterator it = namespaces.find(name_space);
 
390
    if(it != namespaces.end())
 
391
        return it->second;
 
392
 
 
393
    TiXmlElement* docroot;
 
394
 
 
395
    if(name_space.StartsWith(_T("volatile:")))
 
396
    {
 
397
        if(!volatile_doc)
 
398
        {
 
399
            volatile_doc = new TiXmlDocument();
 
400
            volatile_doc->InsertEndChild(TiXmlElement("CodeBlocksConfig"));
 
401
            volatile_doc->SetCondenseWhiteSpace(false);
 
402
        }
 
403
        docroot = volatile_doc->FirstChildElement("CodeBlocksConfig");
 
404
    }
 
405
    else
 
406
    {
 
407
        docroot = doc->FirstChildElement("CodeBlocksConfig");
 
408
        if(!docroot)
 
409
        {
 
410
            wxString err(_("Fatal error parsing supplied configuration file.\nParser error message:\n"));
 
411
            err << wxString::Format(_T("%s\nAt row %d, column: %d."), cbC2U(doc->ErrorDesc()).c_str(), doc->ErrorRow(), doc->ErrorCol());
 
412
            cbThrow(err);
 
413
        }
 
414
    }
 
415
 
 
416
    TiXmlElement* root = docroot->FirstChildElement(cbU2C(name_space));
 
417
 
 
418
    if(!root) // namespace does not exist
 
419
    {
 
420
        docroot->InsertEndChild(TiXmlElement(cbU2C(name_space)));
 
421
        root = docroot->FirstChildElement(cbU2C(name_space));
 
422
    }
 
423
 
 
424
    if(!root) // now what!
 
425
        cbThrow(_T("Unable to create namespace in document tree (actually not possible..?)"));
 
426
 
 
427
    ConfigManager *c = new ConfigManager(root);
 
428
    namespaces[name_space] = c;
 
429
 
 
430
    return c;
 
431
}
 
432
 
 
433
 
 
434
/*
 
435
*  Hack to enable Turkish language. wxString::Upper will convert lowercase 'i' to \u0130 instead of \u0069 in Turkish locale,
 
436
*  which will break the config file when used in a tag
 
437
*/
 
438
inline void to_upper(wxString& s)
 
439
{
 
440
    #if wxCHECK_VERSION(2, 9, 0)
 
441
    wxStringCharType *p = const_cast<wxStringCharType*>(s.wx_str());
 
442
    wxStringCharType q;
 
443
    #else
 
444
    wxChar *p = (wxChar*) s.c_str();
 
445
    wxChar q;
 
446
    #endif
 
447
    size_t len = s.length()+1;
 
448
    for(;--len;++p)
 
449
    {
 
450
        q = *p;
 
451
        if(q >= 'a' && q <= 'z')
 
452
            *p = q - 32;
 
453
    }
 
454
};
 
455
 
 
456
inline void to_lower(wxString& s)
 
457
{
 
458
    #if wxCHECK_VERSION(2, 9, 0)
 
459
    wxStringCharType *p = const_cast<wxStringCharType*>(s.wx_str());
 
460
    wxStringCharType q;
 
461
    #else
 
462
    wxChar *p = (wxChar*) s.c_str();
 
463
    wxChar q;
 
464
    #endif
 
465
    size_t len = s.length()+1;
 
466
    for(;--len;++p)
 
467
    {
 
468
        q = *p;
 
469
        if(q >= 'A' && q <= 'Z')
 
470
            *p = q + 32;
 
471
    }
 
472
};
 
473
 
 
474
 
 
475
/* ------------------------------------------------------------------------------------------------------------------
 
476
*  Functions to retrieve system paths and locate data files in a defined, consistent way.
 
477
*  Please note that the application determines app_path and data_path at runtime and passes the results
 
478
*  to ConfigManager. GetExecutableFolder() and GetDataFolder() are therefore under normal conditions
 
479
*  simply more efficient shortcuts for Read("app_path") and Read("data_path").
 
480
*/
 
481
 
 
482
wxString ConfigManager::GetProxy()
 
483
{
 
484
    return Manager::Get()->GetConfigManager(_T("app"))->Read(_T("network_proxy"));
 
485
}
 
486
 
 
487
 
 
488
wxString ConfigManager::GetFolder(SearchDirs dir)
 
489
{
 
490
    static bool once = 1;
 
491
 
 
492
    if(once)
 
493
    {
 
494
        InitPaths();
 
495
        once = false;
 
496
    }
 
497
 
 
498
    switch (dir)
 
499
    {
 
500
        case sdHome:
 
501
            return ConfigManager::home_folder;
 
502
 
 
503
        case sdBase:
 
504
            return ConfigManager::app_path;
 
505
 
 
506
        case sdTemp:
 
507
            return ConfigManager::temp_folder;
 
508
 
 
509
        case sdConfig:
 
510
            return ConfigManager::config_folder;
 
511
 
 
512
        case sdCurrent:
 
513
            return ::wxGetCwd();
 
514
 
 
515
        case sdPluginsGlobal:
 
516
#ifndef CB_AUTOCONF
 
517
            return ConfigManager::data_path_global + _T("/plugins");
 
518
#else
 
519
            return ConfigManager::plugin_path_global;
 
520
#endif
 
521
 
 
522
        case sdPluginsUser:
 
523
            return ConfigManager::data_path_user   + _T("/plugins");
 
524
 
 
525
        case sdScriptsGlobal:
 
526
            return ConfigManager::data_path_global + _T("/scripts");
 
527
 
 
528
        case sdScriptsUser:
 
529
            return ConfigManager::data_path_user   + _T("/scripts");
 
530
 
 
531
        case sdDataGlobal:
 
532
            return ConfigManager::data_path_global;
 
533
 
 
534
        case sdDataUser:
 
535
            return ConfigManager::data_path_user;
 
536
 
 
537
        default:
 
538
            return wxEmptyString;
 
539
    }
 
540
}
 
541
 
 
542
wxString ConfigManager::LocateDataFile(const wxString& filename, int search_dirs)
 
543
{
 
544
    wxPathList searchPaths;
 
545
 
 
546
    // user dirs have precedence
 
547
    if (search_dirs & sdPluginsUser)
 
548
        searchPaths.Add(GetPluginsFolder(false));
 
549
    if (search_dirs & sdScriptsUser)
 
550
        searchPaths.Add(GetScriptsFolder(false));
 
551
    if (search_dirs & sdDataUser)
 
552
        searchPaths.Add(GetDataFolder(false));
 
553
 
 
554
    // then we have global dirs
 
555
    if (search_dirs & sdPluginsGlobal)
 
556
        searchPaths.Add(GetPluginsFolder(true));
 
557
    if (search_dirs & sdScriptsGlobal)
 
558
        searchPaths.Add(GetScriptsFolder(true));
 
559
    if (search_dirs & sdDataGlobal)
 
560
        searchPaths.Add(GetDataFolder(true));
 
561
 
 
562
    // rest of the dirs
 
563
    if (search_dirs & sdCurrent)
 
564
        searchPaths.Add(::wxGetCwd());
 
565
    if (search_dirs & sdConfig)
 
566
        searchPaths.Add(GetConfigFolder());
 
567
    if (search_dirs & sdHome)
 
568
        searchPaths.Add(GetHomeFolder());
 
569
    if (search_dirs & sdBase)
 
570
        searchPaths.Add(GetExecutableFolder());
 
571
    if (search_dirs & sdTemp)
 
572
        searchPaths.Add(GetTempFolder());
 
573
 
 
574
    // PATH env. var
 
575
    if (search_dirs & sdPath)
 
576
        searchPaths.AddEnvList(_T("PATH"));
 
577
 
 
578
    return searchPaths.FindValidPath(filename);
 
579
}
 
580
 
 
581
 
 
582
 
 
583
/* ------------------------------------------------------------------------------------------------------------------
 
584
*  ConfigManager
 
585
*/
 
586
 
 
587
ConfigManager::ConfigManager(TiXmlElement* r) : doc(r->GetDocument()), root(r), pathNode(r)
 
588
{
 
589
}
 
590
 
 
591
 
 
592
 
 
593
 
 
594
/* ------------------------------------------------------------------------------------------------------------------
 
595
*  Configuration path handling
 
596
*  Note that due to namespaces, you do no longer need to care about saving/restoring the current path in the normal case.
 
597
*  Mostly, there will be only one module working with one namespace, and every namespace keeps track of its own path.
 
598
*  Also, please note that GetPath() is more expensive than it seems (not a mere accessor to a member variable!), while
 
599
*  SetPath() not only sets the current path, but also creates the respective nodes in the XML document if these don't exist.
 
600
*/
 
601
 
 
602
wxString ConfigManager::GetPath() const
 
603
{
 
604
    TiXmlElement *e = pathNode;
 
605
    wxString ret;
 
606
    ret.Alloc(64);
 
607
 
 
608
    ret = cbC2U(e->Value());
 
609
    while((e = e->Parent()->ToElement()) && e != root)
 
610
    {
 
611
        ret.Prepend(_T('/'));
 
612
        ret.Prepend(cbC2U(e->Value()));
 
613
    }
 
614
    ret.Prepend(_T('/'));
 
615
    return ret;
 
616
};
 
617
 
 
618
void ConfigManager::SetPath(const wxString& path)
 
619
{
 
620
    wxString p(path + _T('/'));
 
621
    pathNode = AssertPath(p);
 
622
}
 
623
 
 
624
wxString ConfigManager::InvalidNameMessage(const wxString& what, const wxString& sub, TiXmlElement *localPath) const
 
625
{
 
626
    wxString s;
 
627
    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)."),
 
628
    what.c_str(),
 
629
    sub.c_str(),
 
630
    cbC2U(localPath->Value()).c_str(),
 
631
    cbC2U(root->Value()).c_str());
 
632
 
 
633
    return s;
 
634
}
 
635
 
 
636
 
 
637
TiXmlElement* ConfigManager::AssertPath(wxString& path)
 
638
{
 
639
    Collapse(path);
 
640
 
 
641
    wxString illegal(_T(" -:.\"\'$&()[]<>+#"));
 
642
    size_t i = 0;
 
643
    while((i = path.find_first_of(illegal, i)) != wxString::npos)
 
644
        path[i] = _T('_');
 
645
 
 
646
    TiXmlElement *localPath = pathNode ? pathNode : root;
 
647
 
 
648
    if(path.GetChar(0) == '/')  // absolute path
 
649
    {
 
650
        localPath = root;
 
651
        path = path.Mid(1);
 
652
    }
 
653
 
 
654
    if(path.find(_T('/')) != wxString::npos) // need for path walking
 
655
        to_lower(path);
 
656
 
 
657
    wxString sub;
 
658
 
 
659
    while(path.find(_T('/')) != wxString::npos)
 
660
    {
 
661
        sub = path.BeforeFirst(_T('/'));
 
662
        path = path.AfterFirst(_T('/'));
 
663
 
 
664
        if(localPath != root && sub.IsSameAs(CfgMgrConsts::dotDot))
 
665
            localPath = localPath->Parent()->ToElement();
 
666
        else if(sub.GetChar(0) < _T('a') || sub.GetChar(0) > _T('z'))
 
667
        {
 
668
            cbThrow(InvalidNameMessage(_T("subpath"), sub, localPath));
 
669
        }
 
670
        else
 
671
        {
 
672
            TiXmlElement* n = localPath->FirstChildElement(cbU2C(sub));
 
673
            if(n)
 
674
                localPath = n;
 
675
            else
 
676
                localPath = (TiXmlElement*) localPath->InsertEndChild(TiXmlElement(cbU2C(sub)));
 
677
        }
 
678
    }
 
679
 
 
680
    to_upper(path);
 
681
 
 
682
    if(!path.IsEmpty() && (path.GetChar(0) < _T('A') || path.GetChar(0) > _T('Z')))
 
683
        cbThrow(InvalidNameMessage(_T("key"), path, localPath));
 
684
 
 
685
    return localPath;
 
686
}
 
687
 
 
688
 
 
689
/* -----------------------------------------------------------------------------------------------------
 
690
*  Clear all nodes from your namespace or delete the namespace alltogether (removing it from the config file).
 
691
*  After Delete() returns, the pointer to your instance is invalid.
 
692
*/
 
693
 
 
694
void ConfigManager::Clear()
 
695
{
 
696
    root->Clear();
 
697
}
 
698
 
 
699
void ConfigManager::Delete()
 
700
{
 
701
    CfgMgrBldr * bld = CfgMgrBldr::Get();
 
702
    wxString ns(cbC2U(root->Value()));
 
703
 
 
704
    root->Clear();
 
705
    doc->RootElement()->RemoveChild(root);
 
706
 
 
707
    wxCriticalSectionLocker(bld->cs);
 
708
    NamespaceMap::iterator it = bld->namespaces.find(ns);
 
709
    if(it != bld->namespaces.end())
 
710
        bld->namespaces.erase(it);
 
711
 
 
712
    delete this;
 
713
}
 
714
 
 
715
void ConfigManager::DeleteAll()
 
716
{
 
717
    CfgMgrBldr * bld = CfgMgrBldr::Get();
 
718
    wxString ns(cbC2U(root->Value()));
 
719
 
 
720
    if(!ns.IsSameAs(_T("app")))
 
721
        cbThrow(_T("Illegal attempt to invoke DeleteAll()."));
 
722
 
 
723
    wxCriticalSectionLocker(bld->cs);
 
724
    doc->RootElement()->Clear();
 
725
    for(NamespaceMap::iterator it = bld->namespaces.begin(); it != bld->namespaces.end(); ++it)
 
726
    {
 
727
        delete it->second;
 
728
        bld->namespaces.erase(it);
 
729
    }
 
730
}
 
731
 
 
732
 
 
733
/* ------------------------------------------------------------------------------------------------------------------
 
734
*  Utility functions for writing nodes
 
735
*/
 
736
 
 
737
TiXmlElement* ConfigManager::GetUniqElement(TiXmlElement* p, const wxString& q)
 
738
{
 
739
    TiXmlElement* r;
 
740
    if((r = p->FirstChildElement(cbU2C(q))))
 
741
        return r;
 
742
 
 
743
    return (TiXmlElement*)(p->InsertEndChild(TiXmlElement(cbU2C(q))));
 
744
}
 
745
 
 
746
void ConfigManager::SetNodeText(TiXmlElement* n, const TiXmlText& t)
 
747
{
 
748
    TiXmlNode *c = n->FirstChild();
 
749
    if(c)
 
750
        n->ReplaceChild(c, t);
 
751
    else
 
752
        n->InsertEndChild(t);
 
753
}
 
754
 
 
755
 
 
756
 
 
757
/* ------------------------------------------------------------------------------------------------------------------
 
758
*  Write and read values
 
759
*  Regardless of namespaces, the string keys app_path and data_path always refer to the location of the application's executable
 
760
*  and the data path, respectively. These values are never saved to the configuration, but kept in static variables.
 
761
*  The application makes use of this by "writing" to the configuration file after determining these values at runtime.
 
762
*/
 
763
void ConfigManager::Write(const wxString& name,  const wxString& value, bool ignoreEmpty)
 
764
{
 
765
    if(name.IsSameAs(CfgMgrConsts::app_path))
 
766
    {
 
767
        return;
 
768
    }
 
769
    else if(name.IsSameAs(CfgMgrConsts::data_path))
 
770
    {
 
771
        data_path_global = value;
 
772
        return;
 
773
    }
 
774
    if(ignoreEmpty && value.IsEmpty())
 
775
    {
 
776
        UnSet(name);
 
777
        return;
 
778
    }
 
779
 
 
780
    wxString key(name);
 
781
    TiXmlElement* e = AssertPath(key);
 
782
 
 
783
    TiXmlElement *str = GetUniqElement(e, key);
 
784
 
 
785
    TiXmlElement *s = GetUniqElement(str, _T("str"));
 
786
 
 
787
    TiXmlText t(value.mb_str(wxConvUTF8));
 
788
    t.SetCDATA(true);
 
789
    SetNodeText(s, t);
 
790
}
 
791
 
 
792
void ConfigManager::Write(const wxString& key, const char* str)
 
793
{
 
794
    /* NOTE (mandrav#1#): Do *not* remove 'false' from the call because in ANSI builds,
 
795
    it matches this very function and overflows the stack... */
 
796
    Write(key, cbC2U(str), false);
 
797
};
 
798
 
 
799
wxString ConfigManager::Read(const wxString& name, const wxString& defaultVal)
 
800
{
 
801
    if(name.IsSameAs(CfgMgrConsts::app_path))
 
802
        return app_path;
 
803
    else if(name.IsSameAs(CfgMgrConsts::data_path))
 
804
        return data_path_global;
 
805
 
 
806
    wxString ret;
 
807
 
 
808
    if(Read(name, &ret))
 
809
        return ret;
 
810
    else
 
811
        return defaultVal;
 
812
}
 
813
 
 
814
bool ConfigManager::Read(const wxString& name, wxString* str)
 
815
{
 
816
    if(name.IsSameAs(CfgMgrConsts::app_path))
 
817
    {
 
818
        str->assign(app_path);
 
819
        return true;
 
820
    }
 
821
    else if(name.IsSameAs(CfgMgrConsts::data_path))
 
822
    {
 
823
        str->assign(data_path_global);
 
824
        return true;
 
825
    }
 
826
 
 
827
    wxString key(name);
 
828
    TiXmlElement* e = AssertPath(key);
 
829
 
 
830
    TiXmlHandle parentHandle(e);
 
831
    TiXmlText *t = (TiXmlText *) parentHandle.FirstChild(cbU2C(key)).FirstChild("str").FirstChild().Node();
 
832
 
 
833
    if(t)
 
834
    {
 
835
        str->assign(cbC2U(t->Value()));
 
836
        return true;
 
837
    }
 
838
    return false;
 
839
}
 
840
 
 
841
void ConfigManager::Write(const wxString& name,  const wxColour& c)
 
842
{
 
843
    wxString key(name);
 
844
    TiXmlElement* e = AssertPath(key);
 
845
 
 
846
    TiXmlElement *leaf = GetUniqElement(e, key);
 
847
 
 
848
    TiXmlElement *s = GetUniqElement(leaf, _T("colour"));
 
849
    s->SetAttribute("r", c.Red());
 
850
    s->SetAttribute("g", c.Green());
 
851
    s->SetAttribute("b", c.Blue());
 
852
}
 
853
 
 
854
wxColour ConfigManager::ReadColour(const wxString& name, const wxColour& defaultVal)
 
855
{
 
856
    wxColour ret;
 
857
 
 
858
    if(Read(name, &ret))
 
859
        return ret;
 
860
    else
 
861
        return defaultVal;
 
862
}
 
863
 
 
864
bool ConfigManager::Read(const wxString& name, wxColour* ret)
 
865
{
 
866
    wxString key(name);
 
867
    TiXmlElement* e = AssertPath(key);
 
868
 
 
869
    TiXmlHandle parentHandle(e);
 
870
    TiXmlElement *c = (TiXmlElement *) parentHandle.FirstChild(cbU2C(key)).FirstChild("colour").Element();
 
871
 
 
872
    if(c)
 
873
    {
 
874
        int r, g, b;
 
875
        if(c->QueryIntAttribute("r", &r) == TIXML_SUCCESS
 
876
                && c->QueryIntAttribute("g", &g) == TIXML_SUCCESS
 
877
                && c->QueryIntAttribute("b", &b) == TIXML_SUCCESS)
 
878
            ret->Set(r, g, b);
 
879
        return true;
 
880
    }
 
881
    return false;
 
882
}
 
883
 
 
884
void ConfigManager::Write(const wxString& name,  int value)
 
885
{
 
886
    wxString key(name);
 
887
    TiXmlElement* e = AssertPath(key);
 
888
    TiXmlElement *leaf = GetUniqElement(e, key);
 
889
 
 
890
    leaf->SetAttribute("int", value);
 
891
}
 
892
 
 
893
int  ConfigManager::ReadInt(const wxString& name,  int defaultVal)
 
894
{
 
895
    int ret;
 
896
 
 
897
    if(Read(name, &ret))
 
898
        return ret;
 
899
    else
 
900
        return defaultVal;
 
901
}
 
902
 
 
903
bool ConfigManager::Read(const wxString& name,  int* value)
 
904
{
 
905
    wxString key(name);
 
906
    TiXmlElement* e = AssertPath(key);
 
907
 
 
908
    TiXmlHandle parentHandle(e);
 
909
    TiXmlElement *leaf = parentHandle.FirstChild(cbU2C(key)).Element();
 
910
 
 
911
    if(leaf)
 
912
        return leaf->QueryIntAttribute("int", value) == TIXML_SUCCESS;
 
913
    return false;
 
914
}
 
915
 
 
916
 
 
917
void ConfigManager::Write(const wxString& name,  bool value)
 
918
{
 
919
    wxString key(name);
 
920
    TiXmlElement* e = AssertPath(key);
 
921
    TiXmlElement *leaf = GetUniqElement(e, key);
 
922
 
 
923
    leaf->SetAttribute("bool", value ? "1" : "0");
 
924
}
 
925
 
 
926
bool  ConfigManager::ReadBool(const wxString& name,  bool defaultVal)
 
927
{
 
928
    bool ret;
 
929
 
 
930
    if(Read(name, &ret))
 
931
        return ret;
 
932
    else
 
933
        return defaultVal;
 
934
}
 
935
 
 
936
bool ConfigManager::Read(const wxString& name,  bool* value)
 
937
{
 
938
    wxString key(name);
 
939
    TiXmlElement* e = AssertPath(key);
 
940
 
 
941
    TiXmlHandle parentHandle(e);
 
942
    TiXmlElement *leaf = parentHandle.FirstChild(cbU2C(key)).Element();
 
943
 
 
944
    if(leaf && leaf->Attribute("bool"))
 
945
    {
 
946
        *value = leaf->Attribute("bool")[0] == '1';
 
947
        return true;
 
948
    }
 
949
    return false;
 
950
}
 
951
 
 
952
 
 
953
void ConfigManager::Write(const wxString& name,  double value)
 
954
{
 
955
    wxString key(name);
 
956
    TiXmlElement* e = AssertPath(key);
 
957
    TiXmlElement *leaf = GetUniqElement(e, key);
 
958
 
 
959
    leaf->SetDoubleAttribute("double", value);
 
960
}
 
961
 
 
962
double  ConfigManager::ReadDouble(const wxString& name,  double defaultVal)
 
963
{
 
964
    double ret;
 
965
 
 
966
    if(Read(name, &ret))
 
967
        return ret;
 
968
    else
 
969
        return defaultVal;
 
970
}
 
971
 
 
972
bool ConfigManager::Read(const wxString& name,  double* value)
 
973
{
 
974
    wxString key(name);
 
975
    TiXmlElement* e = AssertPath(key);
 
976
 
 
977
    TiXmlHandle parentHandle(e);
 
978
    TiXmlElement *leaf = parentHandle.FirstChild(cbU2C(key)).Element();
 
979
 
 
980
    if(leaf)
 
981
        return leaf->QueryDoubleAttribute("double", value) == TIXML_SUCCESS;
 
982
    return false;
 
983
}
 
984
 
 
985
 
 
986
void ConfigManager::Set(const wxString& name)
 
987
{
 
988
    wxString key(name);
 
989
    TiXmlElement* e = AssertPath(key);
 
990
    GetUniqElement(e, key);
 
991
}
 
992
 
 
993
void ConfigManager::UnSet(const wxString& name)
 
994
{
 
995
    wxString key(name);
 
996
    TiXmlElement* e = AssertPath(key);
 
997
 
 
998
    TiXmlNode *leaf = GetUniqElement(e, key);
 
999
    e->RemoveChild(leaf);
 
1000
}
 
1001
 
 
1002
bool ConfigManager::Exists(const wxString& name)
 
1003
{
 
1004
    wxString key(name);
 
1005
    TiXmlElement* e = AssertPath(key);
 
1006
 
 
1007
    TiXmlHandle parentHandle(e);
 
1008
    TiXmlElement *leaf = parentHandle.FirstChild(cbU2C(key)).Element();
 
1009
 
 
1010
    return leaf;
 
1011
}
 
1012
 
 
1013
 
 
1014
 
 
1015
void ConfigManager::Write(const wxString& name,  const wxArrayString& arrayString)
 
1016
{
 
1017
    wxString key(name);
 
1018
    TiXmlElement* e = AssertPath(key);
 
1019
 
 
1020
    TiXmlElement *leaf = GetUniqElement(e, key);
 
1021
 
 
1022
    TiXmlElement *as;
 
1023
    as = GetUniqElement(leaf, _T("astr"));
 
1024
    leaf->RemoveChild(as);
 
1025
    as = GetUniqElement(leaf, _T("astr"));
 
1026
 
 
1027
    for(unsigned int i = 0; i < arrayString.GetCount(); ++i)
 
1028
    {
 
1029
        TiXmlElement s("s");
 
1030
 
 
1031
        TiXmlText t(arrayString[i].mb_str(wxConvUTF8));
 
1032
        t.SetCDATA(true);
 
1033
 
 
1034
        s.InsertEndChild(t);
 
1035
        as->InsertEndChild(s);
 
1036
    }
 
1037
}
 
1038
 
 
1039
void ConfigManager::Read(const wxString& name, wxArrayString *arrayString)
 
1040
{
 
1041
    wxString key(name);
 
1042
    TiXmlElement* e = AssertPath(key);
 
1043
 
 
1044
    TiXmlHandle parentHandle(e);
 
1045
    TiXmlNode *asNode = parentHandle.FirstChild(cbU2C(key)).FirstChild("astr").Node();
 
1046
 
 
1047
    TiXmlNode *curr = 0;
 
1048
    if(asNode)
 
1049
    {
 
1050
        while((curr = asNode->IterateChildren("s", curr)))
 
1051
        {
 
1052
            arrayString->Add(cbC2U(curr->FirstChild()->ToText()->Value()));
 
1053
        }
 
1054
    }
 
1055
}
 
1056
 
 
1057
wxArrayString ConfigManager::ReadArrayString(const wxString& name)
 
1058
{
 
1059
    wxArrayString as;
 
1060
    Read(name, &as);
 
1061
    return as;
 
1062
}
 
1063
 
 
1064
void ConfigManager::WriteBinary(const wxString& name,  const wxString& source)
 
1065
{
 
1066
    wxString key(name);
 
1067
    TiXmlElement* e = AssertPath(key);
 
1068
 
 
1069
    TiXmlElement *str = GetUniqElement(e, key);
 
1070
 
 
1071
    TiXmlElement *s = GetUniqElement(str, _T("bin"));
 
1072
    s->SetAttribute("crc", wxCrc32::FromString(source));
 
1073
    SetNodeText(s, TiXmlText(wxBase64::Encode(source).mb_str(wxConvUTF8)));
 
1074
}
 
1075
 
 
1076
void ConfigManager::WriteBinary(const wxString& name,  void* ptr, size_t len)
 
1077
{
 
1078
    wxString s((wxChar*)ptr, len);
 
1079
    WriteBinary(name,  s);
 
1080
}
 
1081
 
 
1082
wxString ConfigManager::ReadBinary(const wxString& name)
 
1083
{
 
1084
    wxString str;
 
1085
    wxString key(name);
 
1086
    TiXmlElement* e = AssertPath(key);
 
1087
    unsigned int crc = 0;
 
1088
 
 
1089
    TiXmlHandle parentHandle(e);
 
1090
    TiXmlElement* bin = parentHandle.FirstChild(cbU2C(key)).FirstChild("bin").Element();
 
1091
 
 
1092
    if(!bin)
 
1093
        return wxEmptyString;
 
1094
 
 
1095
    if(bin->QueryIntAttribute("crc", (int*)&crc) != TIXML_SUCCESS)
 
1096
        return wxEmptyString;
 
1097
 
 
1098
    if (const TiXmlText* t = bin->FirstChild()->ToText())
 
1099
    {
 
1100
        str.assign(cbC2U(t->Value()));
 
1101
        str = wxBase64::Decode(str);
 
1102
        if(crc ==  wxCrc32::FromString(str))
 
1103
            return str;
 
1104
    }
 
1105
    return wxEmptyString;
 
1106
}
 
1107
 
 
1108
 
 
1109
wxArrayString ConfigManager::EnumerateSubPaths(const wxString& path)
 
1110
{
 
1111
    wxString key(path + _T('/')); // the trailing slash hack is required because AssertPath expects a key name
 
1112
    TiXmlNode* e = AssertPath(key);
 
1113
    wxArrayString ret;
 
1114
 
 
1115
    TiXmlElement *curr = 0;
 
1116
    if(e)
 
1117
    {
 
1118
        while(e->IterateChildren(curr) && (curr = e->IterateChildren(curr)->ToElement()))
 
1119
        {
 
1120
            #if wxCHECK_VERSION(2, 9, 0)
 
1121
            wxUniChar c = cbC2U(curr->Value())[0];
 
1122
            #else
 
1123
            wxChar c = *(cbC2U(curr->Value()));
 
1124
            #endif
 
1125
            if(c < _T('A') || c > _T('Z')) // first char must be a letter, uppercase letters are key names
 
1126
                ret.Add(cbC2U(curr->Value()));
 
1127
        }
 
1128
    }
 
1129
    return ret;
 
1130
}
 
1131
 
 
1132
void ConfigManager::DeleteSubPath(const wxString& thePath)
 
1133
{
 
1134
    if(doc->ErrorId())
 
1135
    {
 
1136
        cbMessageBox(wxString(_T("### TinyXML error:\n")) << cbC2U(doc->ErrorDesc()));
 
1137
        doc->ClearError();
 
1138
    }
 
1139
 
 
1140
    wxString path(thePath);
 
1141
    to_lower(path);
 
1142
 
 
1143
    Collapse(path);
 
1144
 
 
1145
    wxString illegal(_T(" :.,;!\"\'$%&()[]<>{}?*+-|#"));
 
1146
    size_t i;
 
1147
    while((i = path.find_first_of(illegal)) != wxString::npos)
 
1148
        path[i] = _T('_');
 
1149
 
 
1150
    if(path.Last() == _T('/'))
 
1151
        path.RemoveLast();
 
1152
 
 
1153
    if(path.IsSameAs(_T("/"))) // this function will refuse to remove root!
 
1154
        return;
 
1155
 
 
1156
    TiXmlElement* parent = pathNode ? pathNode : root;
 
1157
 
 
1158
    if(path.find(_T('/')) != wxString::npos)
 
1159
    {
 
1160
        wxString sub;
 
1161
        do
 
1162
        {
 
1163
            sub = path.BeforeFirst(_T('/'));
 
1164
            path = path.AfterFirst(_T('/'));
 
1165
 
 
1166
            if(sub.IsEmpty())
 
1167
                parent = root;
 
1168
            else if(sub.IsSameAs(_T(".")))
 
1169
                ;
 
1170
            else if(parent != root && sub.IsSameAs(_T("..")))
 
1171
                parent = parent->Parent()->ToElement();
 
1172
            else
 
1173
            {
 
1174
                TiXmlElement* n = parent->FirstChildElement(cbU2C(sub));
 
1175
                if(n)
 
1176
                    parent = n;
 
1177
                else
 
1178
                    return;
 
1179
            }
 
1180
        }
 
1181
        while(path.find(_T('/')) != wxString::npos);
 
1182
    }
 
1183
 
 
1184
    if(!path.IsEmpty())
 
1185
    {
 
1186
        if(TiXmlNode *toRemove = parent->FirstChild(cbU2C(path)))
 
1187
        {
 
1188
            toRemove->Clear();
 
1189
            parent->RemoveChild(toRemove);
 
1190
        }
 
1191
    }
 
1192
}
 
1193
 
 
1194
 
 
1195
wxArrayString ConfigManager::EnumerateKeys(const wxString& path)
 
1196
{
 
1197
    wxString key(path + _T('/')); // the trailing slash hack is required because AssertPath expects a key name
 
1198
    TiXmlNode* e = AssertPath(key);
 
1199
    wxArrayString ret;
 
1200
 
 
1201
    TiXmlElement *curr = 0;
 
1202
    if(e)
 
1203
    {
 
1204
        while(e->IterateChildren(curr) && (curr = e->IterateChildren(curr)->ToElement()))
 
1205
        {
 
1206
            #if wxCHECK_VERSION(2, 9, 0)
 
1207
            wxUniChar c = cbC2U(curr->Value())[0];
 
1208
            #else
 
1209
            wxChar c = *(cbC2U(curr->Value()));
 
1210
            #endif
 
1211
            if(c >= _T('A') && c <= _T('Z')) // opposite of the above
 
1212
                ret.Add(cbC2U(curr->Value()));
 
1213
        }
 
1214
    }
 
1215
    return ret;
 
1216
}
 
1217
 
 
1218
void ConfigManager::Write(const wxString& name, const ISerializable& object)
 
1219
{
 
1220
    wxString key(name);
 
1221
    TiXmlElement* e = AssertPath(key);
 
1222
 
 
1223
    TiXmlElement *obj = GetUniqElement(e, key);
 
1224
 
 
1225
    TiXmlElement *s = GetUniqElement(obj, _T("obj"));
 
1226
    SetNodeText(s, TiXmlText(cbU2C(wxBase64::Encode(object.SerializeOut()))));
 
1227
}
 
1228
 
 
1229
bool ConfigManager::Read(const wxString& name, ISerializable* object)
 
1230
{
 
1231
    wxString str;
 
1232
    wxString key(name);
 
1233
    TiXmlElement* e = AssertPath(key);
 
1234
 
 
1235
    TiXmlHandle parentHandle(e);
 
1236
    TiXmlText *t = (TiXmlText *) parentHandle.FirstChild(cbU2C(key)).FirstChild("obj").FirstChild().Node();
 
1237
 
 
1238
    if(t)
 
1239
    {
 
1240
        str.assign(cbC2U(t->Value()));
 
1241
        object->SerializeIn(wxBase64::Decode(str));
 
1242
    }
 
1243
    return wxEmptyString;
 
1244
}
 
1245
 
 
1246
void ConfigManager::Write(const wxString& name, const ConfigManagerContainer::StringToStringMap& map)
 
1247
{
 
1248
    wxString key(name);
 
1249
    TiXmlElement* e = AssertPath(key);
 
1250
 
 
1251
    TiXmlElement *leaf = GetUniqElement(e, key);
 
1252
 
 
1253
    TiXmlElement *mNode;
 
1254
    mNode = GetUniqElement(leaf, _T("ssmap"));
 
1255
    leaf->RemoveChild(mNode);
 
1256
    mNode = GetUniqElement(leaf, _T("ssmap"));
 
1257
 
 
1258
    for(ConfigManagerContainer::StringToStringMap::const_iterator it = map.begin(); it != map.end(); ++it)
 
1259
    {
 
1260
        TiXmlElement s(cbU2C(it->first));
 
1261
 
 
1262
        TiXmlText t(cbU2C(it->second));
 
1263
        t.SetCDATA(true);
 
1264
 
 
1265
        s.InsertEndChild(t);
 
1266
        mNode->InsertEndChild(s);
 
1267
    }
 
1268
}
 
1269
 
 
1270
void ConfigManager::Read(const wxString& name, ConfigManagerContainer::StringToStringMap* map)
 
1271
{
 
1272
    wxString key(name);
 
1273
    TiXmlElement* e = AssertPath(key);
 
1274
 
 
1275
    TiXmlHandle parentHandle(e);
 
1276
    TiXmlNode *mNode = parentHandle.FirstChild(cbU2C(key)).FirstChild("ssmap").Node();
 
1277
 
 
1278
    TiXmlNode *curr = 0;
 
1279
    if(mNode)
 
1280
    {
 
1281
        while((curr = mNode->IterateChildren(curr)))
 
1282
            (*map)[cbC2U(curr->Value())] = cbC2U(curr->FirstChild()->ToText()->Value());
 
1283
    }
 
1284
}
 
1285
 
 
1286
ConfigManagerContainer::StringToStringMap ConfigManager::ReadSSMap(const wxString& name)
 
1287
{
 
1288
    ConfigManagerContainer::StringToStringMap ret;
 
1289
    Read(name, &ret);
 
1290
    return ret;
 
1291
}
 
1292
 
 
1293
void ConfigManager::Write(const wxString& name, const ConfigManagerContainer::IntToStringMap& map)
 
1294
{
 
1295
    wxString key(name);
 
1296
    TiXmlElement* e = AssertPath(key);
 
1297
 
 
1298
    TiXmlElement *leaf = GetUniqElement(e, key);
 
1299
 
 
1300
    TiXmlElement *mNode;
 
1301
    mNode = GetUniqElement(leaf, _T("ismap"));
 
1302
    leaf->RemoveChild(mNode);
 
1303
    mNode = GetUniqElement(leaf, _T("ismap"));
 
1304
 
 
1305
    wxString tmp;
 
1306
    for(ConfigManagerContainer::IntToStringMap::const_iterator it = map.begin(); it != map.end(); ++it)
 
1307
    {
 
1308
        tmp.Printf(_T("x%d"), (int) it->first);
 
1309
        TiXmlElement s(tmp.mb_str());
 
1310
 
 
1311
        TiXmlText t(cbU2C(it->second));
 
1312
        t.SetCDATA(true);
 
1313
 
 
1314
        s.InsertEndChild(t);
 
1315
        mNode->InsertEndChild(s);
 
1316
    }
 
1317
}
 
1318
 
 
1319
void ConfigManager::Read(const wxString& name, ConfigManagerContainer::IntToStringMap* map)
 
1320
{
 
1321
    wxString key(name);
 
1322
    TiXmlElement* e = AssertPath(key);
 
1323
 
 
1324
    TiXmlHandle parentHandle(e);
 
1325
    TiXmlNode *mNode = parentHandle.FirstChild(cbU2C(key)).FirstChild("ismap").Node();
 
1326
 
 
1327
    TiXmlNode *curr = 0;
 
1328
    long tmp;
 
1329
    if(mNode)
 
1330
    {
 
1331
        while((curr = mNode->IterateChildren(curr)))
 
1332
        {
 
1333
            cbC2U(curr->Value()).Mid(1).ToLong(&tmp);
 
1334
            (*map)[tmp] = cbC2U(curr->FirstChild()->ToText()->Value());
 
1335
        }
 
1336
    }
 
1337
}
 
1338
 
 
1339
ConfigManagerContainer::IntToStringMap ConfigManager::ReadISMap(const wxString& name)
 
1340
{
 
1341
    ConfigManagerContainer::IntToStringMap ret;
 
1342
    Read(name, &ret);
 
1343
    return ret;
 
1344
}
 
1345
 
 
1346
 
 
1347
 
 
1348
 
 
1349
 
 
1350
 
 
1351
void ConfigManager::Write(const wxString& name, const ConfigManagerContainer::StringSet& set)
 
1352
{
 
1353
    wxString key(name);
 
1354
    TiXmlElement* e = AssertPath(key);
 
1355
 
 
1356
    TiXmlElement *leaf = GetUniqElement(e, key);
 
1357
 
 
1358
    TiXmlElement *mNode;
 
1359
    mNode = GetUniqElement(leaf, _T("sset"));
 
1360
    leaf->RemoveChild(mNode);
 
1361
    mNode = GetUniqElement(leaf, _T("sset"));
 
1362
 
 
1363
    for(ConfigManagerContainer::StringSet::const_iterator it = set.begin(); it != set.end(); ++it)
 
1364
    {
 
1365
        TiXmlElement s("s");
 
1366
 
 
1367
        TiXmlText t(cbU2C(*it));
 
1368
        t.SetCDATA(true);
 
1369
 
 
1370
        s.InsertEndChild(t);
 
1371
        mNode->InsertEndChild(s);
 
1372
    }
 
1373
}
 
1374
 
 
1375
 
 
1376
void ConfigManager::Read(const wxString& name, ConfigManagerContainer::StringSet* set)
 
1377
{
 
1378
    wxString key(name);
 
1379
    TiXmlElement* e = AssertPath(key);
 
1380
 
 
1381
    TiXmlHandle parentHandle(e);
 
1382
    TiXmlNode *mNode = parentHandle.FirstChild(cbU2C(key)).FirstChild("sset").Node();
 
1383
 
 
1384
    TiXmlNode *curr = 0;
 
1385
    if(mNode)
 
1386
    {
 
1387
        while((curr = mNode->IterateChildren(curr)))
 
1388
            set->insert(cbC2U(curr->FirstChild()->ToText()->Value()));
 
1389
    }
 
1390
}
 
1391
 
 
1392
ConfigManagerContainer::StringSet ConfigManager::ReadSSet(const wxString& name)
 
1393
{
 
1394
    ConfigManagerContainer::StringSet ret;
 
1395
    Read(name, &ret);
 
1396
    return ret;
 
1397
}
 
1398
 
 
1399
 
 
1400
void ConfigManager::Write(const wxString& name, const ConfigManagerContainer::SerializableObjectMap* map)
 
1401
{
 
1402
    wxString key(name);
 
1403
    TiXmlElement* e = AssertPath(key);
 
1404
 
 
1405
    TiXmlElement *leaf = GetUniqElement(e, key);
 
1406
 
 
1407
    TiXmlElement *mNode;
 
1408
    mNode = GetUniqElement(leaf, _T("objmap"));
 
1409
    leaf->RemoveChild(mNode);
 
1410
    mNode = GetUniqElement(leaf, _T("objmap"));
 
1411
 
 
1412
    for(ConfigManagerContainer::SerializableObjectMap::const_iterator it = map->begin(); it != map->end(); ++it)
 
1413
    {
 
1414
        TiXmlElement s(cbU2C(it->first));
 
1415
        s.InsertEndChild(TiXmlText(cbU2C(wxBase64::Encode(it->second->SerializeOut()))));
 
1416
        mNode->InsertEndChild(s);
 
1417
    }
 
1418
}
 
1419
 
 
1420
 
 
1421
void ConfigManager::InitPaths()
 
1422
{
 
1423
#ifdef __WINDOWS__
 
1424
    ConfigManager::config_folder = GetPortableConfigDir();
 
1425
#else
 
1426
    ConfigManager::config_folder = wxStandardPathsBase::Get().GetUserDataDir();
 
1427
#endif
 
1428
    ConfigManager::home_folder = wxStandardPathsBase::Get().GetUserConfigDir();
 
1429
    ConfigManager::app_path = ::DetermineExecutablePath();
 
1430
    wxString res_path = ::DetermineResourcesPath();
 
1431
 
 
1432
    // if non-empty, the app has overriden it (e.g. "--prefix" was passed in the command line)
 
1433
    if (data_path_global.IsEmpty())
 
1434
    {
 
1435
        if(platform::windows)
 
1436
            ConfigManager::data_path_global = app_path + _T("/share/codeblocks");
 
1437
        else if(platform::macosx)
 
1438
            ConfigManager::data_path_global = res_path + _T("/share/codeblocks");
 
1439
        else
 
1440
            ConfigManager::data_path_global = wxStandardPathsBase::Get().GetDataDir();
 
1441
    }
 
1442
#ifdef CB_AUTOCONF
 
1443
    if (plugin_path_global.IsEmpty())
 
1444
    {
 
1445
        if(platform::windows || platform::macosx)
 
1446
            ConfigManager::plugin_path_global = data_path_global;
 
1447
        else
 
1448
        {
 
1449
            ConfigManager::plugin_path_global = wxStandardPathsBase::Get().GetPluginsDir() + _T("/plugins");
 
1450
            // first assume, we use standard-paths
 
1451
            if(!wxDirExists(ConfigManager::plugin_path_global) && wxIsPlatform64Bit())
 
1452
            {
 
1453
                // if standard-path does not exist and we are on 64-bit system, use lib64 instead
 
1454
                ConfigManager::plugin_path_global = ((const wxStandardPaths&)wxStandardPaths::Get()).GetInstallPrefix() + _T("/lib64/codeblocks/plugins");
 
1455
            }
 
1456
        }
 
1457
    }
 
1458
#endif
 
1459
 
 
1460
    ConfigManager::data_path_user = ConfigManager::relo ? data_path_global : config_folder + _T("/share/codeblocks");
 
1461
 
 
1462
    CreateDirRecursively(ConfigManager::config_folder);
 
1463
    CreateDirRecursively(ConfigManager::data_path_user   + _T("/plugins/"));
 
1464
    CreateDir(ConfigManager::data_path_user   + _T("/scripts/"));
 
1465
 
 
1466
    ConfigManager::temp_folder = wxStandardPathsBase::Get().GetTempDir();
 
1467
};
 
1468
 
 
1469
 
 
1470