X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8650108199bf799f21e29811cddaefd579c98c88..cc4d5638c66a409e421420ed7110917755a66788:/src/common/config.cpp?ds=sidebyside diff --git a/src/common/config.cpp b/src/common/config.cpp index c4ae2ed8d1..852dd13f17 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -4,8 +4,7 @@ // Author: Vadim Zeitlin // Modified by: // Created: 07.04.98 -// RCS-ID: $Id$ -// Copyright: (c) 1997 Karsten Ballüder Ballueder@usa.net +// Copyright: (c) 1997 Karsten Ballueder Ballueder@usa.net // Vadim Zeitlin // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// @@ -43,6 +42,7 @@ #include #include #include // for INT_MAX +#include // for FLT_MAX // ---------------------------------------------------------------------------- // global and class static variables @@ -62,10 +62,8 @@ bool wxConfigBase::ms_bAutoCreate = true; wxConfigBase *wxAppTraitsBase::CreateConfig() { return new - #if defined(__WXMSW__) && wxUSE_CONFIG_NATIVE + #if defined(__WINDOWS__) && wxUSE_CONFIG_NATIVE wxRegConfig(wxTheApp->GetAppName(), wxTheApp->GetVendorName()); - #elif defined(__WXPALMOS__) && wxUSE_CONFIG_NATIVE - wxPrefConfig(wxTheApp->GetAppName()); #else // either we're under Unix or wish to use files even under Windows wxFileConfig(wxTheApp->GetAppName()); #endif @@ -105,7 +103,7 @@ wxConfigBase *wxConfigBase::Create() { if ( ms_bAutoCreate && ms_pConfig == NULL ) { wxAppTraits * const traits = wxTheApp ? wxTheApp->GetTraits() : NULL; - wxCHECK_MSG( traits, NULL, _T("create wxApp before calling this") ); + wxCHECK_MSG( traits, NULL, wxT("create wxApp before calling this") ); ms_pConfig = traits->CreateConfig(); } @@ -121,7 +119,7 @@ wxConfigBase *wxConfigBase::Create() #define IMPLEMENT_READ_FOR_TYPE(name, type, deftype, extra) \ bool wxConfigBase::Read(const wxString& key, type *val) const \ { \ - wxCHECK_MSG( val, false, _T("wxConfig::Read(): NULL parameter") ); \ + wxCHECK_MSG( val, false, wxT("wxConfig::Read(): NULL parameter") ); \ \ if ( !DoRead##name(key, val) ) \ return false; \ @@ -135,7 +133,7 @@ wxConfigBase *wxConfigBase::Create() type *val, \ deftype defVal) const \ { \ - wxCHECK_MSG( val, false, _T("wxConfig::Read(): NULL parameter") ); \ + wxCHECK_MSG( val, false, wxT("wxConfig::Read(): NULL parameter") ); \ \ bool read = DoRead##name(key, val); \ if ( !read ) \ @@ -156,38 +154,79 @@ wxConfigBase *wxConfigBase::Create() IMPLEMENT_READ_FOR_TYPE(String, wxString, const wxString&, ExpandEnvVars) IMPLEMENT_READ_FOR_TYPE(Long, long, long, long) -IMPLEMENT_READ_FOR_TYPE(Int, int, int, int) IMPLEMENT_READ_FOR_TYPE(Double, double, double, double) IMPLEMENT_READ_FOR_TYPE(Bool, bool, bool, bool) #undef IMPLEMENT_READ_FOR_TYPE -// the DoReadXXX() for the other types have implementation in the base class -// but can be overridden in the derived ones -bool wxConfigBase::DoReadInt(const wxString& key, int *pi) const +// int is stored as long +bool wxConfigBase::Read(const wxString& key, int *pi) const { - wxCHECK_MSG( pi, false, _T("wxConfig::Read(): NULL parameter") ); + long l = *pi; + bool r = Read(key, &l); + wxASSERT_MSG( l < INT_MAX, wxT("int overflow in wxConfig::Read") ); + *pi = (int)l; + return r; +} - long l; - if ( !DoReadLong(key, &l) ) +bool wxConfigBase::Read(const wxString& key, int *pi, int defVal) const +{ + long l = *pi; + bool r = Read(key, &l, defVal); + wxASSERT_MSG( l < INT_MAX, wxT("int overflow in wxConfig::Read") ); + *pi = (int)l; + return r; +} + +// Read floats as doubles then just type cast it down. +bool wxConfigBase::Read(const wxString& key, float* val) const +{ + wxCHECK_MSG( val, false, wxT("wxConfig::Read(): NULL parameter") ); + + double temp; + if ( !Read(key, &temp) ) return false; - wxASSERT_MSG( l < INT_MAX, _T("overflow in wxConfig::DoReadInt") ); + wxCHECK_MSG( fabs(temp) <= FLT_MAX, false, + wxT("float overflow in wxConfig::Read") ); + wxCHECK_MSG( (temp == 0.0) || (fabs(temp) >= FLT_MIN), false, + wxT("float underflow in wxConfig::Read") ); - *pi = (int)l; + *val = static_cast(temp); return true; } +bool wxConfigBase::Read(const wxString& key, float* val, float defVal) const +{ + wxCHECK_MSG( val, false, wxT("wxConfig::Read(): NULL parameter") ); + + if ( Read(key, val) ) + return true; + + *val = defVal; + return false; +} + +// the DoReadXXX() for the other types have implementation in the base class +// but can be overridden in the derived ones bool wxConfigBase::DoReadBool(const wxString& key, bool* val) const { - wxCHECK_MSG( val, false, _T("wxConfig::Read(): NULL parameter") ); + wxCHECK_MSG( val, false, wxT("wxConfig::Read(): NULL parameter") ); long l; if ( !DoReadLong(key, &l) ) return false; - wxASSERT_MSG( l == 0 || l == 1, _T("bad bool value in wxConfig::DoReadInt") ); + if ( l != 0 && l != 1 ) + { + // Don't assert here as this could happen in the result of user editing + // the file directly and this not indicate a bug in the program but + // still complain that something is wrong. + wxLogWarning(_("Invalid value %ld for a boolean key \"%s\" in " + "config file."), + l, key); + } *val = l != 0; @@ -199,7 +238,14 @@ bool wxConfigBase::DoReadDouble(const wxString& key, double* val) const wxString str; if ( Read(key, &str) ) { - return str.ToDouble(val); + if ( str.ToCDouble(val) ) + return true; + + // Previous versions of wxFileConfig wrote the numbers out using the + // current locale and not the C one as now, so attempt to parse the + // string as a number in the current locale too, for compatibility. + if ( str.ToDouble(val) ) + return true; } return false; @@ -222,12 +268,10 @@ wxString wxConfigBase::ExpandEnvVars(const wxString& str) const bool wxConfigBase::DoWriteDouble(const wxString& key, double val) { - return DoWriteString(key, wxString::Format(_T("%g"), val)); -} - -bool wxConfigBase::DoWriteInt(const wxString& key, int value) -{ - return DoWriteLong(key, (long)value); + // Notice that we always write out the numbers in C locale and not the + // current one. This makes the config files portable between machines using + // different locales. + return DoWriteString(key, wxString::FromCDouble(val)); } bool wxConfigBase::DoWriteBool(const wxString& key, bool value) @@ -243,10 +287,11 @@ wxConfigPathChanger::wxConfigPathChanger(const wxConfigBase *pContainer, const wxString& strEntry) { m_bChanged = false; - m_pContainer = (wxConfigBase *)pContainer; + m_pContainer = const_cast(pContainer); - // the path is everything which precedes the last slash - wxString strPath = strEntry.BeforeLast(wxCONFIG_PATH_SEPARATOR); + // the path is everything which precedes the last slash and the name is + // everything after it -- and this works correctly if there is no slash too + wxString strPath = strEntry.BeforeLast(wxCONFIG_PATH_SEPARATOR, &m_strName); // except in the special case of "/keyname" when there is nothing before "/" if ( strPath.empty() && @@ -271,20 +316,13 @@ wxConfigPathChanger::wxConfigPathChanger(const wxConfigBase *pContainer, pConfig->SetPath(wxT("MySettings")); pConfig->SetPath(wxT("..")); int value; - pConfig->Read(_T("MainWindowX"), & value); + pConfig->Read(wxT("MainWindowX"), & value); */ m_strOldPath = m_pContainer->GetPath().wc_str(); if ( *m_strOldPath.c_str() != wxCONFIG_PATH_SEPARATOR ) m_strOldPath += wxCONFIG_PATH_SEPARATOR; m_pContainer->SetPath(strPath); } - - // in any case, use the just the name, not full path - m_strName = strEntry.AfterLast(wxCONFIG_PATH_SEPARATOR); - } - else { - // it's a name only, without path - nothing to do - m_strName = strEntry; } } @@ -346,7 +384,7 @@ enum Bracket Bracket_None, Bracket_Normal = ')', Bracket_Curly = '}', -#ifdef __WXMSW__ +#ifdef __WINDOWS__ Bracket_Windows = '%', // yeah, Windows people are a bit strange ;-) #endif Bracket_Max @@ -360,17 +398,17 @@ wxString wxExpandEnvVars(const wxString& str) size_t m; for ( size_t n = 0; n < str.length(); n++ ) { switch ( str[n].GetValue() ) { -#ifdef __WXMSW__ +#ifdef __WINDOWS__ case wxT('%'): -#endif //WINDOWS +#endif // __WINDOWS__ case wxT('$'): { Bracket bracket; - #ifdef __WXMSW__ + #ifdef __WINDOWS__ if ( str[n] == wxT('%') ) bracket = Bracket_Windows; else - #endif //WINDOWS + #endif // __WINDOWS__ if ( n == str.length() - 1 ) { bracket = Bracket_None; } @@ -395,7 +433,7 @@ wxString wxExpandEnvVars(const wxString& str) while ( m < str.length() && (wxIsalnum(str[m]) || str[m] == wxT('_')) ) m++; - + wxString strVarName(str.c_str() + n + 1, m - n - 1); #ifdef __WXWINCE__ @@ -414,7 +452,7 @@ wxString wxExpandEnvVars(const wxString& str) #endif { // variable doesn't exist => don't change anything - #ifdef __WXMSW__ + #ifdef __WINDOWS__ if ( bracket != Bracket_Windows ) #endif if ( bracket != Bracket_None ) @@ -431,10 +469,10 @@ wxString wxExpandEnvVars(const wxString& str) // // under Unix, OTOH, this warning could be useful for the user to // understand why isn't the variable expanded as intended - #ifndef __WXMSW__ + #ifndef __WINDOWS__ wxLogWarning(_("Environment variables expansion failed: missing '%c' at position %u in '%s'."), (char)bracket, (unsigned int) (m + 1), str.c_str()); - #endif // __WXMSW__ + #endif // __WINDOWS__ } else { // skip closing bracket unless the variables wasn't expanded @@ -481,9 +519,13 @@ void wxSplitPath(wxArrayString& aParts, const wxString& path) else if ( strCurrent == wxT("..") ) { // go up one level if ( aParts.size() == 0 ) + { wxLogWarning(_("'%s' has extra '..', ignored."), path); + } else + { aParts.erase(aParts.end() - 1); + } strCurrent.Empty(); }