]>
git.saurik.com Git - wxWidgets.git/blob - src/common/config.cpp
30ca1fa2e7cdc0ad71715cf0cbf2b6fddbdd137c
   1 /////////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     implementation of wxConfigBase class 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 1997 Karsten Ballüder   Ballueder@usa.net 
   9 //                       Vadim Zeitlin      <zeitlin@dptmaths.ens-cachan.fr> 
  10 // Licence:     wxWindows licence 
  11 /////////////////////////////////////////////////////////////////////////////// 
  13 // ---------------------------------------------------------------------------- 
  15 // ---------------------------------------------------------------------------- 
  16 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  17     #pragma implementation "confbase.h" 
  20 #include "wx/wxprec.h" 
  26 #ifndef wxUSE_CONFIG_NATIVE 
  27     #define wxUSE_CONFIG_NATIVE 1 
  30 #include "wx/config.h" 
  33 #include "wx/arrstr.h" 
  35 #if wxUSE_CONFIG && ((wxUSE_FILE && wxUSE_TEXTFILE) || wxUSE_CONFIG_NATIVE) 
  39 #include "wx/textfile.h" 
  46 #include <limits.h>     // for INT_MAX 
  48 // ---------------------------------------------------------------------------- 
  49 // global and class static variables 
  50 // ---------------------------------------------------------------------------- 
  52 wxConfigBase 
*wxConfigBase::ms_pConfig     
= NULL
; 
  53 bool          wxConfigBase::ms_bAutoCreate 
= true; 
  55 // ============================================================================ 
  57 // ============================================================================ 
  59 // ---------------------------------------------------------------------------- 
  61 // ---------------------------------------------------------------------------- 
  63 // Not all args will always be used by derived classes, but including them all 
  64 // in each class ensures compatibility. 
  65 wxConfigBase::wxConfigBase(const wxString
& appName
, 
  66                            const wxString
& vendorName
, 
  67                            const wxString
& WXUNUSED(localFilename
), 
  68                            const wxString
& WXUNUSED(globalFilename
), 
  70             : m_appName(appName
), m_vendorName(vendorName
), m_style(style
) 
  72     m_bExpandEnvVars 
= true; 
  73     m_bRecordDefaults 
= false; 
  76 wxConfigBase::~wxConfigBase() 
  78     // required here for Darwin 
  81 wxConfigBase 
*wxConfigBase::Set(wxConfigBase 
*pConfig
) 
  83   wxConfigBase 
*pOld 
= ms_pConfig
; 
  88 wxConfigBase 
*wxConfigBase::Create() 
  90   if ( ms_bAutoCreate 
&& ms_pConfig 
== NULL 
) { 
  92     #if defined(__WXMSW__) && wxUSE_CONFIG_NATIVE 
  93         new wxRegConfig(wxTheApp
->GetAppName(), wxTheApp
->GetVendorName()); 
  94     #else // either we're under Unix or wish to use files even under Windows 
  95       new wxFileConfig(wxTheApp
->GetAppName()); 
 102 // ---------------------------------------------------------------------------- 
 103 // wxConfigBase reading entries 
 104 // ---------------------------------------------------------------------------- 
 106 // implement both Read() overloads for the given type in terms of DoRead() 
 107 #define IMPLEMENT_READ_FOR_TYPE(name, type, deftype, extra)                 \ 
 108     bool wxConfigBase::Read(const wxString& key, type *val) const           \ 
 110         wxCHECK_MSG( val, false, _T("wxConfig::Read(): NULL parameter") );  \ 
 112         if ( !DoRead##name(key, val) )                                      \ 
 115         *val = extra(*val);                                                 \ 
 120     bool wxConfigBase::Read(const wxString& key,                            \ 
 122                             deftype defVal) const                           \ 
 124         wxCHECK_MSG( val, false, _T("wxConfig::Read(): NULL parameter") );  \ 
 126         bool read = DoRead##name(key, val);                                 \ 
 129             if ( IsRecordingDefaults() )                                    \ 
 131                 ((wxConfigBase *)this)->DoWrite##name(key, defVal);         \ 
 137         *val = extra(*val);                                                 \ 
 143 IMPLEMENT_READ_FOR_TYPE(String
, wxString
, const wxString
&, ExpandEnvVars
) 
 144 IMPLEMENT_READ_FOR_TYPE(Long
, long, long, long) 
 145 IMPLEMENT_READ_FOR_TYPE(Int
, int, int, int) 
 146 IMPLEMENT_READ_FOR_TYPE(Double
, double, double, double) 
 147 IMPLEMENT_READ_FOR_TYPE(Bool
, bool, bool, bool) 
 149 #undef IMPLEMENT_READ_FOR_TYPE 
 151 // the DoReadXXX() for the other types have implementation in the base class 
 152 // but can be overridden in the derived ones 
 153 bool wxConfigBase::DoReadInt(const wxString
& key
, int *pi
) const 
 155     wxCHECK_MSG( pi
, false, _T("wxConfig::Read(): NULL parameter") ); 
 158     if ( !DoReadLong(key
, &l
) ) 
 161     wxASSERT_MSG( l 
< INT_MAX
, _T("overflow in wxConfig::DoReadInt") ); 
 168 bool wxConfigBase::DoReadBool(const wxString
& key
, bool* val
) const 
 170     wxCHECK_MSG( val
, false, _T("wxConfig::Read(): NULL parameter") ); 
 173     if ( !DoReadLong(key
, &l
) ) 
 176     wxASSERT_MSG( l 
== 0 || l 
== 1, _T("bad bool value in wxConfig::DoReadInt") ); 
 183 bool wxConfigBase::DoReadDouble(const wxString
& key
, double* val
) const 
 186     if ( Read(key
, &str
) ) 
 188         return str
.ToDouble(val
); 
 194 // string reading helper 
 195 wxString 
wxConfigBase::ExpandEnvVars(const wxString
& str
) const 
 197     wxString tmp
; // Required for BC++ 
 198     if (IsExpandingEnvVars()) 
 199         tmp 
= wxExpandEnvVars(str
); 
 205 // ---------------------------------------------------------------------------- 
 206 // wxConfigBase writing 
 207 // ---------------------------------------------------------------------------- 
 209 bool wxConfigBase::DoWriteDouble(const wxString
& key
, double val
) 
 211     return DoWriteString(key
, wxString::Format(_T("%g"), val
)); 
 214 bool wxConfigBase::DoWriteInt(const wxString
& key
, int value
) 
 216     return DoWriteLong(key
, (long)value
); 
 219 bool wxConfigBase::DoWriteBool(const wxString
& key
, bool value
) 
 221     return DoWriteLong(key
, value 
? 1l : 0l); 
 224 // ---------------------------------------------------------------------------- 
 225 // wxConfigPathChanger 
 226 // ---------------------------------------------------------------------------- 
 228 wxConfigPathChanger::wxConfigPathChanger(const wxConfigBase 
*pContainer
, 
 229                                  const wxString
& strEntry
) 
 231   m_pContainer 
= (wxConfigBase 
*)pContainer
; 
 233   // the path is everything which precedes the last slash 
 234   wxString strPath 
= strEntry
.BeforeLast(wxCONFIG_PATH_SEPARATOR
); 
 236   // except in the special case of "/keyname" when there is nothing before "/" 
 237   if ( strPath
.IsEmpty() && 
 238        ((!strEntry
.IsEmpty()) && strEntry
[0] == wxCONFIG_PATH_SEPARATOR
) ) 
 240     strPath 
= wxCONFIG_PATH_SEPARATOR
; 
 243   if ( !strPath
.IsEmpty() ) 
 245     if ( m_pContainer
->GetPath() != strPath 
) 
 247         // do change the path 
 249         m_strOldPath 
= m_pContainer
->GetPath(); 
 250         if ( *m_strOldPath
.c_str() != wxCONFIG_PATH_SEPARATOR 
) 
 251           m_strOldPath 
+= wxCONFIG_PATH_SEPARATOR
; 
 252         m_pContainer
->SetPath(strPath
); 
 255     // in any case, use the just the name, not full path 
 256     m_strName 
= strEntry
.AfterLast(wxCONFIG_PATH_SEPARATOR
); 
 259     // it's a name only, without path - nothing to do 
 261     m_strName 
= strEntry
; 
 265 wxConfigPathChanger::~wxConfigPathChanger() 
 267   // only restore path if it was changed 
 269     m_pContainer
->SetPath(m_strOldPath
); 
 273 #endif // wxUSE_CONFIG 
 275 // ---------------------------------------------------------------------------- 
 276 // static & global functions 
 277 // ---------------------------------------------------------------------------- 
 279 // understands both Unix and Windows (but only under Windows) environment 
 280 // variables expansion: i.e. $var, $(var) and ${var} are always understood 
 281 // and in addition under Windows %var% is also. 
 282 wxString 
wxExpandEnvVars(const wxString
& str
) 
 285   strResult
.Alloc(str
.Len()); 
 287   // don't change the values the enum elements: they must be equal 
 288   // to the matching [closing] delimiter. 
 292     Bracket_Normal  
= ')', 
 295     Bracket_Windows 
= '%',    // yeah, Windows people are a bit strange ;-) 
 301   for ( size_t n 
= 0; n 
< str
.Len(); n
++ ) { 
 310             if ( str
[n
] == wxT('%') ) 
 311               bracket 
= Bracket_Windows
; 
 314           if ( n 
== str
.Len() - 1 ) { 
 315             bracket 
= Bracket_None
; 
 318             switch ( str
[n 
+ 1] ) { 
 320                 bracket 
= Bracket_Normal
; 
 321                 n
++;                   // skip the bracket 
 325                 bracket 
= Bracket_Curly
; 
 326                 n
++;                   // skip the bracket 
 330                 bracket 
= Bracket_None
; 
 336           while ( m 
< str
.Len() && (wxIsalnum(str
[m
]) || str
[m
] == wxT('_')) ) 
 339           wxString 
strVarName(str
.c_str() + n 
+ 1, m 
- n 
- 1); 
 342           const wxChar 
*pszValue 
= NULL
; 
 344           const wxChar 
*pszValue 
= wxGetenv(strVarName
); 
 346           if ( pszValue 
!= NULL 
) { 
 347             strResult 
+= pszValue
; 
 350             // variable doesn't exist => don't change anything 
 352               if ( bracket 
!= Bracket_Windows 
) 
 354                 if ( bracket 
!= Bracket_None 
) 
 355                   strResult 
<< str
[n 
- 1]; 
 356             strResult 
<< str
[n
] << strVarName
; 
 359           // check the closing bracket 
 360           if ( bracket 
!= Bracket_None 
) { 
 361             if ( m 
== str
.Len() || str
[m
] != (wxChar
)bracket 
) { 
 362               // under MSW it's common to have '%' characters in the registry 
 363               // and it's annoying to have warnings about them each time, so 
 364               // ignroe them silently if they are not used for env vars 
 366               // under Unix, OTOH, this warning could be useful for the user to 
 367               // understand why isn't the variable expanded as intended 
 369                 wxLogWarning(_("Environment variables expansion failed: missing '%c' at position %d in '%s'."), 
 370                              (char)bracket
, m 
+ 1, str
.c_str()); 
 374               // skip closing bracket unless the variables wasn't expanded 
 375               if ( pszValue 
== NULL 
) 
 376                 strResult 
<< (char)bracket
; 
 381           n 
= m 
- 1;  // skip variable name 
 386         // backslash can be used to suppress special meaning of % and $ 
 387         if ( n 
!= str
.Len() - 1 && 
 388                 (str
[n 
+ 1] == wxT('%') || str
[n 
+ 1] == wxT('$')) ) { 
 389           strResult 
+= str
[++n
]; 
 403 // this function is used to properly interpret '..' in path 
 404 void wxSplitPath(wxArrayString
& aParts
, const wxChar 
*sz
) 
 409   const wxChar 
*pc 
= sz
; 
 411     if ( *pc 
== wxT('\0') || *pc 
== wxCONFIG_PATH_SEPARATOR 
) { 
 412       if ( strCurrent 
== wxT(".") ) { 
 415       else if ( strCurrent 
== wxT("..") ) { 
 417         if ( aParts
.size() == 0 ) 
 418           wxLogWarning(_("'%s' has extra '..', ignored."), sz
); 
 420           aParts
.erase(aParts
.end() - 1); 
 424       else if ( !strCurrent
.IsEmpty() ) { 
 425         aParts
.push_back(strCurrent
); 
 429         // could log an error here, but we prefer to ignore extra '/' 
 431       if ( *pc 
== wxT('\0') )