1) APPCONF_ constants renamed to wxCONFIG_

2) wxConfig::Create() now chooses the best (native) implemenntation of
   wxConfig instead of calling wxApp::CreateConfig which was suppressed
3) wxFileConfig(const char *appname) ctor added which looks for the config
   file(s) in standard location(s)


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@398 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 1998-07-29 12:03:42 +00:00
parent 580c10e3ca
commit da468d387d
4 changed files with 232 additions and 129 deletions

View File

@ -3,16 +3,16 @@
// 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"
@ -32,23 +32,26 @@
// ----------------------------------------------------------------------------
/// 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
// ----------------------------------------------------------------------------
@ -70,8 +73,8 @@ extern void wxSplitPath(wxArrayString& aParts, const char *sz);
// ----------------------------------------------------------------------------
// 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
@ -85,16 +88,21 @@ public:
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)
@ -171,8 +179,8 @@ public:
}
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,
@ -186,7 +194,7 @@ protected:
~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
@ -203,5 +211,5 @@ private:
static wxConfig *ms_pConfig;
};
#endif //_APPCONF_H
#endif //_wxCONFIG_H

View File

@ -1,17 +1,14 @@
/*****************************************************************************\
* 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
@ -83,7 +80,19 @@
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
@ -103,9 +112,17 @@ public:
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();
@ -176,9 +193,17 @@ public:
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);

View File

@ -37,9 +37,19 @@
#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()
// ----------------------------------------------------------------------------
@ -55,9 +65,6 @@ wxConfig *wxConfig::ms_pConfig = NULL;
// ----------------------------------------------------------------------------
// wxConfig
// ----------------------------------------------------------------------------
wxConfig::~wxConfig()
{
}
wxConfig *wxConfig::Set(wxConfig *pConfig)
{
@ -66,9 +73,19 @@ 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
@ -89,18 +106,18 @@ wxConfig::PathChanger::PathChanger(const wxConfig *pContainer,
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 {
@ -231,7 +248,7 @@ void wxSplitPath(wxArrayString& aParts, const char *sz)
wxString strCurrent;
const char *pc = sz;
for ( ;; ) {
if ( *pc == '\0' || *pc == APPCONF_PATH_SEPARATOR ) {
if ( *pc == '\0' || *pc == wxCONFIG_PATH_SEPARATOR ) {
if ( strCurrent == "." ) {
// ignore
}

View File

@ -58,7 +58,7 @@
// ----------------------------------------------------------------------------
// 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); }
@ -79,26 +79,67 @@ static wxString FilterOut(const wxString& str);
// ----------------------------------------------------------------------------
// static functions
// ----------------------------------------------------------------------------
wxString wxFileConfig::GetGlobalFileName(const char *szFile)
wxString wxFileConfig::GetGlobalDir()
{
wxString str;
wxString strDir;
bool bNoExt = strchr(szFile, '.') == NULL;
#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";
strDir = szWinDir;
strDir << '\\';
#endif // Unix/Windows
return strDir;
}
wxString wxFileConfig::GetLocalDir()
{
wxString strDir;
#ifdef __UNIX__
const char *szHome = getenv("HOME");
if ( szHome == NULL ) {
// we're homeless...
wxLogWarning(_("can't find user's HOME, using current directory."));
strDir = ".";
}
else
strDir = szHome;
#else // Windows
#ifdef __WIN32__
const char *szHome = getenv("HOMEDRIVE");
if ( szHome != NULL )
strDir << szHome;
szHome = getenv("HOMEPATH");
if ( szHome != NULL )
strDir << szHome;
#else // Win16
// Win16 has no idea about home, so use the current directory instead
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;
@ -106,32 +147,17 @@ wxString wxFileConfig::GetGlobalFileName(const char *szFile)
wxString wxFileConfig::GetLocalFileName(const char *szFile)
{
wxString str;
wxString str = GetLocalDir();
#ifdef __UNIX__
const char *szHome = getenv("HOME");
if ( szHome == NULL ) {
// we're homeless...
wxLogWarning(_("can't find user's HOME, using current directory."));
szHome = ".";
}
str << szHome << "/." << szFile;
#else // Windows
#ifdef __WIN32__
const char *szHome = getenv("HOMEDRIVE");
if ( szHome != NULL )
str << szHome;
szHome = getenv("HOMEPATH");
if ( szHome != NULL )
str << szHome;
str << szFile;
if ( strchr(szFile, '.') == NULL )
str << ".ini";
#else // Win16
// Win16 has no idea about home, so use the current directory instead
str << ".\\" << szFile;
#endif // WIN16/32
#endif // UNIX/Win
str << '.';
#endif
str << szFile;
#ifdef __WXMSW__
str << ".ini";
#endif
return str;
}
@ -148,47 +174,64 @@ void wxFileConfig::Init()
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;
@ -199,6 +242,13 @@ wxFileConfig::~wxFileConfig()
}
}
wxFileConfig::~wxFileConfig()
{
Flush();
CleanUp();
}
// ----------------------------------------------------------------------------
// parse a config file
// ----------------------------------------------------------------------------
@ -242,7 +292,7 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
// 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);
@ -349,14 +399,14 @@ void wxFileConfig::SetPath(const wxString& strPath)
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);
}
@ -373,7 +423,7 @@ void wxFileConfig::SetPath(const wxString& strPath)
// 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];
}
}
@ -527,9 +577,9 @@ bool wxFileConfig::Write(const char *szKey, const char *szValue)
// 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;
}
@ -614,10 +664,13 @@ bool wxFileConfig::DeleteGroup(const char *szKey)
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);
@ -849,7 +902,7 @@ wxFileConfig::LineList *wxFileConfig::ConfigGroup::GetLastEntryLine()
wxString wxFileConfig::ConfigGroup::GetFullName() const
{
if ( Parent() )
return Parent()->GetFullName() + APPCONF_PATH_SEPARATOR + Name();
return Parent()->GetFullName() + wxCONFIG_PATH_SEPARATOR + Name();
else
return "";
}
@ -872,7 +925,7 @@ wxFileConfig::ConfigGroup::FindEntry(const char *szName) const
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);
@ -902,7 +955,7 @@ wxFileConfig::ConfigGroup::FindSubgroup(const char *szName) const
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);
@ -1097,7 +1150,7 @@ wxFileConfig::ConfigEntry::ConfigEntry(wxFileConfig::ConfigGroup *pParent,
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
}
@ -1172,7 +1225,7 @@ void wxFileConfig::ConfigEntry::SetDirty()
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());
@ -1182,7 +1235,7 @@ int CompareEntries(wxFileConfig::ConfigEntry *p1,
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());