// Purpose: declaration of the base class of all config implementations
// (see also: fileconf.h and msw/regconf.h)
// Author: Karsten Ballüder & Vadim Zeitlin
-// Modified by:
+// Modified by:
// Created: 07.04.98 (adapted from appconf.h)
// RCS-ID: $Id$
-// Copyright: (c) 1997 Karsten Ballüder Ballueder@usa.net
+// Copyright: (c) 1997 Karsten Ballüder Ballueder@usa.net
// Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
// Licence: wxWindows license
///////////////////////////////////////////////////////////////////////////////
-#ifndef _APPCONF_H
-#define _APPCONF_H
+#ifndef _wxCONFIG_H
+#define _wxCONFIG_H
#ifdef __GNUG__
#pragma interface "config.h"
// ----------------------------------------------------------------------------
/// shall we be case sensitive in parsing variable names?
-#ifndef APPCONF_CASE_SENSITIVE
- #define APPCONF_CASE_SENSITIVE FALSE
+#ifndef wxCONFIG_CASE_SENSITIVE
+ #define wxCONFIG_CASE_SENSITIVE FALSE
#endif
-/// separates group and entry names
-#ifndef APPCONF_PATH_SEPARATOR
- #define APPCONF_PATH_SEPARATOR '/'
+/// separates group and entry names (probably shouldn't be changed)
+#ifndef wxCONFIG_PATH_SEPARATOR
+ #define wxCONFIG_PATH_SEPARATOR '/'
#endif
/// introduces immutable entries
-#ifndef APPCONF_IMMUTABLE_PREFIX
- #define APPCONF_IMMUTABLE_PREFIX '!'
+// (i.e. the ones which can't be changed from the local config file)
+#ifndef wxCONFIG_IMMUTABLE_PREFIX
+ #define wxCONFIG_IMMUTABLE_PREFIX '!'
#endif
/// should we use registry instead of configuration files under Win32?
-#ifndef APPCONF_WIN32_NATIVE
- #define APPCONF_WIN32_NATIVE TRUE
+// (i.e. whether wxConfig::Create() will create a wxFileConfig (if it's FALSE) or
+// wxRegConfig (if it's true and we're under Win32) or wxIniConfig (Win16))
+#ifndef wxCONFIG_WIN32_NATIVE
+ #define wxCONFIG_WIN32_NATIVE TRUE
#endif
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// abstract base class wxConfig which defines the interface for derived classes
//
-// wxConfig organizes the items in a tree-like structure (modeled after the
-// Unix/Dos filesystem). There are groups (directories) and keys (files).
+// wxConfig organizes the items in a tree-like structure (modeled after the
+// Unix/Dos filesystem). There are groups (directories) and keys (files).
// There is always one current group given by the current path.
//
// Keys are pairs "key_name = value" where value may be of string or integer
static wxConfig *Set(wxConfig *pConfig);
// get the config object, creates it on demand
static wxConfig *Get() { if ( !ms_pConfig ) Create(); return ms_pConfig; }
- // create a new config object
- static void Create();
+ // create a new config object: this function will create the "best"
+ // implementation of wxConfig available for the current platform, see
+ // comments near definition wxCONFIG_WIN32_NATIVE for details. It returns
+ // the created object and also sets it as ms_pConfig.
+ static wxConfig *Create();
// ctor & virtual dtor
+ // environment variable expansion is on by default
wxConfig() { m_bExpandEnvVars = TRUE; }
- virtual ~wxConfig();
+ // empty but ensures that dtor of all derived classes is virtual
+ virtual ~wxConfig() { }
// path management
// set current path: if the first character is '/', it's the absolute path,
- // otherwise it's a relative path. '..' is supported. If the strPath
+ // otherwise it's a relative path. '..' is supported. If the strPath
// doesn't exist it is created.
virtual void SetPath(const wxString& strPath) = 0;
// retrieve the current path (always as absolute path)
}
protected:
- static bool IsImmutable(const char *szKey)
- { return *szKey == APPCONF_IMMUTABLE_PREFIX; }
+ static bool IsImmutable(const char *szKey)
+ { return *szKey == wxCONFIG_IMMUTABLE_PREFIX; }
// a handy little class which changes current path to the path of given entry
// and restores it in dtor: so if you declare a local variable of this type,
~PathChanger();
// get the key name
- const wxString& Name() const { return m_strName; }
+ const wxString& Name() const { return m_strName; }
private:
wxConfig *m_pContainer; // object we live in
static wxConfig *ms_pConfig;
};
-#endif //_APPCONF_H
+#endif //_wxCONFIG_H
-/*****************************************************************************\
- * Project: CppLib: C++ library for Windows/UNIX platfroms *
- * File: fileconf.h - file based implementation of Config *
- *---------------------------------------------------------------------------*
- * Language: C++ *
- * Platfrom: Any *
- *---------------------------------------------------------------------------*
- * Classes: *
- *---------------------------------------------------------------------------*
- * Author: Vadim Zeitlin zeitlin@dptmaths.ens-cachan.fr> *
- * adapted from earlier class by VZ & Karsten Ballüder *
- * History: *
- * 27.04.98 created *
-\*****************************************************************************/
+///////////////////////////////////////////////////////////////////////////////
+// Name: fileconf.h
+// Purpose: wxFileConfig derivation of wxConfig
+// Author: Vadim Zeitlin
+// Modified by:
+// Created: 07.04.98 (adapted from appconf.cpp)
+// RCS-ID: $Id$
+// Copyright: (c) 1997 Karsten Ballüder & Vadim Zeitlin
+// Ballueder@usa.net <zeitlin@dptmaths.ens-cachan.fr>
+// Licence: wxWindows license
+///////////////////////////////////////////////////////////////////////////////
#ifndef _FILECONF_H
#define _FILECONF_H
and local value is ignored. Of course, the changes are always written to local
file only.
- @@@@ describe environment variable expansion
+ The names of these files can be specified in a number of ways. First of all,
+ you can use the standard convention: using the ctor which takes 'strAppName'
+ parameter will probably be sufficient for 90% of cases. If, for whatever
+ reason you wish to use the files with some other names, you can always use the
+ second ctor.
+
+ wxFileConfig also may automatically expand the values of environment variables
+ in the entries it reads: for example, if you have an entry
+ score_file = $HOME/.score
+ a call to Read(&str, "score_file") will return a complete path to .score file
+ unless the expansion was previousle disabled with SetExpandEnvVars(FALSE) call
+ (it's on by default, the current status can be retrieved with
+ IsExpandingEnvVars function).
*/
class wxFileConfig : public wxConfig
static wxString GetLocalFileName(const char *szFile);
// ctor & dtor
- // if strGlobal is empty, only local config file is used
- wxFileConfig(const wxString& strLocal,
- const wxString& strGlobal = "");
+ // the names of local and global (if not disabled) config files are
+ // constructed using Get{Local|Global}FileName functions described above
+ // (szAppName is just the (short) name of your application)
+ wxFileConfig(const char *szAppName, bool bLocalOnly = FALSE);
+ // this ctor allows you to specify custom names for both files (if strGlobal
+ // isn't a full path, it's considered to be relative to the standard
+ // directory, i.e. /etc under Unix and %windir% under Windows, if strLocal
+ // is not an absolute path, it's considered to be relative to the user's
+ // directory). If either of strings is empty, the corresponding file is not
+ // used.
+ wxFileConfig(const wxString& strLocal, const wxString& strGlobal);
// dtor will save unsaved data
virtual ~wxFileConfig();
bool LineListIsEmpty();
private:
- // put the object in the initial state
+ // GetXXXFileame helpers: return ('/' terminated) directory names
+ static wxString GetGlobalDir();
+ static wxString GetLocalDir();
+
+ // common part of all ctors (assumes that m_str{Local|Global}File are already
+ // initialized
void Init();
+ // common part of from dtor and DeleteAll
+ void CleanUp();
+
// parse the whole file
void Parse(wxTextFile& file, bool bLocal);
#include <wx/log.h>
#include <wx/textfile.h>
#include <wx/config.h>
-#include <wx/fileconf.h>
-#include <stdlib.h>
+// we must include (one of) these files for wxConfig::Create
+#if defined(__MSWIN__) && defined(wxCONFIG_WIN32_NATIVE)
+ #ifdef __WIN32__
+ #include <wx/msw/regconf.h>
+ #else //WIN16
+ #include <wx/msw/iniconf.h>
+ #endif
+#else // either we're under Unix or wish to use files even under Windows
+ #include <wx/fileconf.h>
+#endif
+
+#include <stdlib.h>
#include <ctype.h> // for isalnum()
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// wxConfig
// ----------------------------------------------------------------------------
-wxConfig::~wxConfig()
-{
-}
wxConfig *wxConfig::Set(wxConfig *pConfig)
{
return pOld;
}
-void wxConfig::Create()
+wxConfig *wxConfig::Create()
{
- ms_pConfig = wxTheApp->CreateConfig();
+ return ms_pConfig =
+#if defined(__MSWIN__) && defined(wxCONFIG_WIN32_NATIVE)
+ #ifdef __WIN32__
+ new wxRegConfig(wxTheApp->GetAppName(), wxTheApp->GetVendorName());
+ #else //WIN16
+ #error "Sorry, no wxIniConfig yet..."
+ //new wxIniConfig(wxTheApp->GetAppName(), wxTheApp->GetVendorName());
+ #endif
+#else // either we're under Unix or wish to use files even under Windows
+ new wxFileConfig(wxTheApp->GetAppName());
+#endif
}
const char *wxConfig::Read(const char *szKey, const char *szDefault) const
const wxString& strEntry)
{
m_pContainer = (wxConfig *)pContainer;
- wxString strPath = strEntry.Before(APPCONF_PATH_SEPARATOR);
+ wxString strPath = strEntry.Before(wxCONFIG_PATH_SEPARATOR);
// special case of "/keyname" when there is nothing before "/"
- if ( strPath.IsEmpty() && strEntry[0] == APPCONF_PATH_SEPARATOR )
- strPath = APPCONF_PATH_SEPARATOR;
+ if ( strPath.IsEmpty() && strEntry[0] == wxCONFIG_PATH_SEPARATOR )
+ strPath = wxCONFIG_PATH_SEPARATOR;
if ( !strPath.IsEmpty() ) {
// do change the path
m_bChanged = TRUE;
- m_strName = strEntry.Right(APPCONF_PATH_SEPARATOR);
+ m_strName = strEntry.Right(wxCONFIG_PATH_SEPARATOR);
m_strOldPath = m_pContainer->GetPath();
- m_strOldPath += APPCONF_PATH_SEPARATOR;
+ m_strOldPath += wxCONFIG_PATH_SEPARATOR;
m_pContainer->SetPath(strPath);
}
else {
wxString strCurrent;
const char *pc = sz;
for ( ;; ) {
- if ( *pc == '\0' || *pc == APPCONF_PATH_SEPARATOR ) {
+ if ( *pc == '\0' || *pc == wxCONFIG_PATH_SEPARATOR ) {
if ( strCurrent == "." ) {
// ignore
}
// ----------------------------------------------------------------------------
// is 'c' a valid character in group name?
-// NB: APPCONF_IMMUTABLE_PREFIX and APPCONF_PATH_SEPARATOR must be valid chars,
+// NB: wxCONFIG_IMMUTABLE_PREFIX and wxCONFIG_PATH_SEPARATOR must be valid chars,
// but _not_ ']' (group name delimiter)
inline bool IsValid(char c) { return isalnum(c) || strchr("@_/-!.*%", c); }
// ----------------------------------------------------------------------------
// static functions
// ----------------------------------------------------------------------------
-wxString wxFileConfig::GetGlobalFileName(const char *szFile)
+wxString wxFileConfig::GetGlobalDir()
{
- wxString str;
-
- bool bNoExt = strchr(szFile, '.') == NULL;
+ wxString strDir;
- #ifdef __UNIX__
- str << "/etc/" << szFile;
- if ( bNoExt )
- str << ".conf";
- #else // Windows
+ #ifdef __UNIX__
+ strDir = "/etc/";
+ #else // Windows
#ifndef _MAX_PATH
#define _MAX_PATH 512
#endif
char szWinDir[_MAX_PATH];
::GetWindowsDirectory(szWinDir, _MAX_PATH);
- str << szWinDir << "\\" << szFile;
- if ( bNoExt )
- str << ".ini";
- #endif // UNIX/Win
- return str;
+ strDir = szWinDir;
+ strDir << '\\';
+ #endif // Unix/Windows
+
+ return strDir;
}
-wxString wxFileConfig::GetLocalFileName(const char *szFile)
+wxString wxFileConfig::GetLocalDir()
{
- wxString str;
+ wxString strDir;
- #ifdef __UNIX__
+ #ifdef __UNIX__
const char *szHome = getenv("HOME");
if ( szHome == NULL ) {
// we're homeless...
wxLogWarning(_("can't find user's HOME, using current directory."));
- szHome = ".";
+ strDir = ".";
}
- str << szHome << "/." << szFile;
+ else
+ strDir = szHome;
#else // Windows
#ifdef __WIN32__
const char *szHome = getenv("HOMEDRIVE");
if ( szHome != NULL )
- str << szHome;
+ strDir << szHome;
szHome = getenv("HOMEPATH");
if ( szHome != NULL )
- str << szHome;
- str << szFile;
- if ( strchr(szFile, '.') == NULL )
- str << ".ini";
+ strDir << szHome;
#else // Win16
// Win16 has no idea about home, so use the current directory instead
- str << ".\\" << szFile;
+ strDir = ".\\";
#endif // WIN16/32
#endif // UNIX/Win
+ return strDir;
+}
+
+wxString wxFileConfig::GetGlobalFileName(const char *szFile)
+{
+ wxString str = GetLocalDir();
+ str << szFile;
+
+ if ( strchr(szFile, '.') == NULL )
+ #ifdef __UNIX__
+ str << ".conf";
+ #else // Windows
+ str << ".ini";
+ #endif // UNIX/Win
+
+ return str;
+}
+
+wxString wxFileConfig::GetLocalFileName(const char *szFile)
+{
+ wxString str = GetLocalDir();
+
+ #ifdef __UNIX__
+ str << '.';
+ #endif
+
+ str << szFile;
+
+ #ifdef __WXMSW__
+ str << ".ini";
+ #endif
+
return str;
}
m_linesHead =
m_linesTail = NULL;
- m_strPath.Empty();
-}
-
-wxFileConfig::wxFileConfig(const wxString& strLocal, const wxString& strGlobal)
- : m_strLocalFile(strLocal), m_strGlobalFile(strGlobal)
-{
- Init();
-
// it's not an error if (one of the) file(s) doesn't exist
// parse the global file
- if ( !strGlobal.IsEmpty() ) {
- if ( wxFile::Exists(strGlobal) ) {
- wxTextFile fileGlobal(strGlobal);
+ if ( !m_strGlobalFile.IsEmpty() && wxFile::Exists(m_strGlobalFile) ) {
+ wxTextFile fileGlobal(m_strGlobalFile);
- if ( fileGlobal.Open() ) {
- Parse(fileGlobal, FALSE /* global */);
- SetRootPath();
- }
- else
- wxLogWarning(_("can't open global configuration file '%s'."),
- strGlobal.c_str());
+ if ( fileGlobal.Open() ) {
+ Parse(fileGlobal, FALSE /* global */);
+ SetRootPath();
}
+ else
+ wxLogWarning(_("can't open global configuration file '%s'."),
+ m_strGlobalFile.c_str());
}
// parse the local file
- if ( wxFile::Exists(strLocal) ) {
- wxTextFile fileLocal(strLocal);
+ if ( !m_strLocalFile.IsEmpty() && wxFile::Exists(m_strLocalFile) ) {
+ wxTextFile fileLocal(m_strLocalFile);
if ( fileLocal.Open() ) {
Parse(fileLocal, TRUE /* local */);
SetRootPath();
}
else
wxLogWarning(_("can't open user configuration file '%s'."),
- strLocal.c_str());
+ m_strLocalFile.c_str());
}
}
-wxFileConfig::~wxFileConfig()
+wxFileConfig::wxFileConfig(const char *szAppName, bool bLocalOnly)
+{
+ wxASSERT( !IsEmpty(szAppName) ); // invent a name for your application!
+
+ m_strLocalFile = GetLocalFileName(szAppName);
+ if ( !bLocalOnly )
+ m_strGlobalFile = GetGlobalFileName(szAppName);
+ //else: it's going to be empty and we won't use the global file
+
+ Init();
+}
+
+wxFileConfig::wxFileConfig(const wxString& strLocal, const wxString& strGlobal)
+ : m_strLocalFile(strLocal), m_strGlobalFile(strGlobal)
+{
+ // if the path is not absolute, prepend the standard directory to it
+
+ if ( !strLocal.IsEmpty() && !wxIsPathSeparator(strLocal[0u]) )
+ m_strLocalFile = GetLocalDir();
+ m_strLocalFile << strLocal;
+
+ if ( !strGlobal.IsEmpty() && !wxIsPathSeparator(strGlobal[0u]) )
+ m_strGlobalFile = GetGlobalDir();
+ m_strGlobalFile << strGlobal;
+
+ Init();
+}
+
+void wxFileConfig::CleanUp()
{
- Flush();
delete m_pRootGroup;
LineList *pCur = m_linesHead;
}
}
+wxFileConfig::~wxFileConfig()
+{
+ Flush();
+
+ CleanUp();
+}
+
// ----------------------------------------------------------------------------
// parse a config file
// ----------------------------------------------------------------------------
// group name here is always considered as abs path
wxString strGroup;
pStart++;
- strGroup << APPCONF_PATH_SEPARATOR << wxString(pStart, pEnd - pStart);
+ strGroup << wxCONFIG_PATH_SEPARATOR << wxString(pStart, pEnd - pStart);
// will create it if doesn't yet exist
SetPath(strGroup);
return;
}
- if ( strPath[0] == APPCONF_PATH_SEPARATOR ) {
+ if ( strPath[0] == wxCONFIG_PATH_SEPARATOR ) {
// absolute path
wxSplitPath(aParts, strPath);
}
else {
// relative path, combine with current one
wxString strFullPath = m_strPath;
- strFullPath << APPCONF_PATH_SEPARATOR << strPath;
+ strFullPath << wxCONFIG_PATH_SEPARATOR << strPath;
wxSplitPath(aParts, strFullPath);
}
// recombine path parts in one variable
m_strPath.Empty();
for ( n = 0; n < aParts.Count(); n++ ) {
- m_strPath << APPCONF_PATH_SEPARATOR << aParts[n];
+ m_strPath << wxCONFIG_PATH_SEPARATOR << aParts[n];
}
}
// writing an entry
// check that the name is reasonable
- if ( strName[0u] == APPCONF_IMMUTABLE_PREFIX ) {
+ if ( strName[0u] == wxCONFIG_IMMUTABLE_PREFIX ) {
wxLogError(_("Entry name can't start with '%c'."),
- APPCONF_IMMUTABLE_PREFIX);
+ wxCONFIG_IMMUTABLE_PREFIX);
return FALSE;
}
bool wxFileConfig::DeleteAll()
{
- const char *szFile = m_strLocalFile;
- delete m_pRootGroup;
+ CleanUp();
+
+ m_strLocalFile = m_strGlobalFile = "";
Init();
+ const char *szFile = m_strLocalFile;
+
if ( remove(szFile) == -1 )
wxLogSysError(_("can't delete user configuration file '%s'"), szFile);
wxString wxFileConfig::ConfigGroup::GetFullName() const
{
if ( Parent() )
- return Parent()->GetFullName() + APPCONF_PATH_SEPARATOR + Name();
+ return Parent()->GetFullName() + wxCONFIG_PATH_SEPARATOR + Name();
else
return "";
}
i = (lo + hi)/2;
pEntry = m_aEntries[i];
- #if APPCONF_CASE_SENSITIVE
+ #if wxCONFIG_CASE_SENSITIVE
res = strcmp(pEntry->Name(), szName);
#else
res = Stricmp(pEntry->Name(), szName);
i = (lo + hi)/2;
pGroup = m_aSubgroups[i];
- #if APPCONF_CASE_SENSITIVE
+ #if wxCONFIG_CASE_SENSITIVE
res = strcmp(pGroup->Name(), szName);
#else
res = Stricmp(pGroup->Name(), szName);
m_bDirty = FALSE;
- m_bImmutable = strName[0] == APPCONF_IMMUTABLE_PREFIX;
+ m_bImmutable = strName[0] == wxCONFIG_IMMUTABLE_PREFIX;
if ( m_bImmutable )
m_strName.erase(0, 1); // remove first character
}
int CompareEntries(wxFileConfig::ConfigEntry *p1,
wxFileConfig::ConfigEntry *p2)
{
- #if APPCONF_CASE_SENSITIVE
+ #if wxCONFIG_CASE_SENSITIVE
return strcmp(p1->Name(), p2->Name());
#else
return Stricmp(p1->Name(), p2->Name());
int CompareGroups(wxFileConfig::ConfigGroup *p1,
wxFileConfig::ConfigGroup *p2)
{
- #if APPCONF_CASE_SENSITIVE
+ #if wxCONFIG_CASE_SENSITIVE
return strcmp(p1->Name(), p2->Name());
#else
return Stricmp(p1->Name(), p2->Name());