From 807a903e6807ae3e49928bda488a04bc0d832149 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 21 Apr 2001 01:46:19 +0000 Subject: [PATCH] merged optimizations from 2.2 git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@9820 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/msw/regconf.h | 73 +++++---- include/wx/msw/registry.h | 21 +-- src/common/log.cpp | 129 +++++++++------- src/common/wincmn.cpp | 8 +- src/msw/regconf.cpp | 318 +++++++++++++++++++++++++++++++------- src/msw/registry.cpp | 39 +++-- src/msw/utils.cpp | 18 ++- 7 files changed, 429 insertions(+), 177 deletions(-) diff --git a/include/wx/msw/regconf.h b/include/wx/msw/regconf.h index 8cad906888..5ed19b74e1 100644 --- a/include/wx/msw/regconf.h +++ b/include/wx/msw/regconf.h @@ -29,10 +29,10 @@ class WXDLLEXPORT wxRegConfig : public wxConfigBase public: // ctor & dtor // will store data in HKLM\appName and HKCU\appName - wxRegConfig(const wxString& appName = "", - const wxString& vendorName = "", - const wxString& localFilename = "", - const wxString& globalFilename = "", + wxRegConfig(const wxString& appName = _T(""), + const wxString& vendorName = _T(""), + const wxString& localFilename = _T(""), + const wxString& globalFilename = _T(""), long style = 0); // dtor will save unsaved data @@ -65,37 +65,37 @@ public: // read/write bool Read(const wxString& key, wxString *pStr) const; bool Read(const wxString& key, wxString *pStr, const wxString& szDefault) const; - wxString Read(const wxString& key, const wxString& defVal) const - { return wxConfigBase::Read(key, defVal); } - + wxString Read(const wxString& key, const wxString& defVal) const + { return wxConfigBase::Read(key, defVal); } + bool Read(const wxString& key, long *plResult) const; - bool Read(const wxString& key, long *pl, long defVal) const - { return wxConfigBase::Read(key, pl, defVal); } + bool Read(const wxString& key, long *pl, long defVal) const + { return wxConfigBase::Read(key, pl, defVal); } long Read(const wxString& key, long defVal) const - { return wxConfigBase::Read(key, defVal); } - + { return wxConfigBase::Read(key, defVal); } + // The following are necessary to satisfy the compiler bool Read(const wxString& key, int *pi, int defVal) const - { return wxConfigBase::Read(key, pi, defVal); } - bool Read(const wxString& key, int *pi) const - { return wxConfigBase::Read(key, pi); } - - bool Read(const wxString& key, double* val, double defVal) const - { return wxConfigBase::Read(key, val, defVal); } - bool Read(const wxString& key, double* val) const - { return wxConfigBase::Read(key, val); } - - bool Read(const wxString& key, bool *pb, bool defVal) const - { return wxConfigBase::Read(key, pb, defVal); } - bool Read(const wxString& key, bool *pb) const - { return wxConfigBase::Read(key, pb); } - + { return wxConfigBase::Read(key, pi, defVal); } + bool Read(const wxString& key, int *pi) const + { return wxConfigBase::Read(key, pi); } + + bool Read(const wxString& key, double* val, double defVal) const + { return wxConfigBase::Read(key, val, defVal); } + bool Read(const wxString& key, double* val) const + { return wxConfigBase::Read(key, val); } + + bool Read(const wxString& key, bool *pb, bool defVal) const + { return wxConfigBase::Read(key, pb, defVal); } + bool Read(const wxString& key, bool *pb) const + { return wxConfigBase::Read(key, pb); } + bool Write(const wxString& key, const wxString& szValue); bool Write(const wxString& key, long lValue); - bool Write(const wxString& key, double dValue) - { return wxConfigBase::Write(key, dValue); } - bool Write(const wxString& key, bool bValue) - { return wxConfigBase::Write(key, bValue); } + bool Write(const wxString& key, double dValue) + { return wxConfigBase::Write(key, dValue); } + bool Write(const wxString& key, bool bValue) + { return wxConfigBase::Write(key, bValue); } virtual bool Flush(bool /* bCurrentOnly = FALSE */ ) { return TRUE; } @@ -108,6 +108,21 @@ public: virtual bool DeleteGroup(const wxString& key); virtual bool DeleteAll(); +protected: + // opens the local key creating it if necessary and returns it + wxRegKey& LocalKey() const // must be const to be callable from const funcs + { + wxRegConfig* self = wxConstCast(this, wxRegConfig); + + if ( !m_keyLocal.IsOpened() ) + { + // create on demand + self->m_keyLocal.Create(); + } + + return self->m_keyLocal; + } + private: // no copy ctor/assignment operator wxRegConfig(const wxRegConfig&); diff --git a/include/wx/msw/registry.h b/include/wx/msw/registry.h index 1a6bf68fcf..76980b5f64 100644 --- a/include/wx/msw/registry.h +++ b/include/wx/msw/registry.h @@ -16,15 +16,6 @@ #pragma interface "registry.h" #endif -// ---------------------------------------------------------------------------- -// mutable hack (see also registry.cpp) -// ---------------------------------------------------------------------------- -#if wxUSE_MUTABLE - #define MUTABLE mutable -#else - #define MUTABLE -#endif - // ---------------------------------------------------------------------------- // types used in this module // ---------------------------------------------------------------------------- @@ -217,7 +208,17 @@ public: bool GetFirstKey (wxString& strKeyName , long& lIndex); bool GetNextKey (wxString& strKeyName , long& lIndex) const; + // for wxRegConfig usage only: preallocate some memory for the name + void ReserveMemoryForName(size_t bytes) { m_strKey.reserve(bytes); } + private: + // common part of all ctors + void Init() + { + m_hKey = (WXHKEY) NULL; + m_dwLastError = 0; + } + // no copy ctor/assignment operator wxRegKey(const wxRegKey& key); // not implemented wxRegKey& operator=(const wxRegKey& key); // not implemented @@ -226,7 +227,7 @@ private: m_hRootKey; // handle of the top key (i.e. StdKey) wxString m_strKey; // key name (relative to m_hRootKey) - MUTABLE long m_dwLastError; // last error (0 if none) + long m_dwLastError; // last error (0 if none) }; #endif //_REGISTRY_H diff --git a/src/common/log.cpp b/src/common/log.cpp index 97f406c81f..0f30a9e562 100644 --- a/src/common/log.cpp +++ b/src/common/log.cpp @@ -96,6 +96,12 @@ static wxCriticalSection gs_csLogBuf; #endif // wxUSE_THREADS +// return true if we have a non NULL non disabled log target +static inline bool IsLoggingEnabled() +{ + return wxLog::IsEnabled() && (wxLog::GetActiveTarget() != NULL); +} + // ---------------------------------------------------------------------------- // implementation of Log functions // @@ -106,6 +112,7 @@ static wxCriticalSection gs_csLogBuf; // generic log function void wxLogGeneric(wxLogLevel level, const wxChar *szFormat, ...) { +<<<<<<< log.cpp if ( wxLog::GetActiveTarget() != NULL ) { wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); @@ -113,24 +120,38 @@ void wxLogGeneric(wxLogLevel level, const wxChar *szFormat, ...) va_start(argptr, szFormat); wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); va_end(argptr); +======= + if ( IsLoggingEnabled() ) { + wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); +>>>>>>> 1.93.2.3 +<<<<<<< log.cpp wxLog::OnLog(level, s_szBuf, time(NULL)); } +======= + va_list argptr; + va_start(argptr, szFormat); + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); + va_end(argptr); + + wxLog::OnLog(level, s_szBuf, time(NULL)); + } +>>>>>>> 1.93.2.3 } -#define IMPLEMENT_LOG_FUNCTION(level) \ - void wxLog##level(const wxChar *szFormat, ...) \ - { \ - if ( wxLog::GetActiveTarget() != NULL ) { \ - wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); \ - \ - va_list argptr; \ - va_start(argptr, szFormat); \ - wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); \ - va_end(argptr); \ - \ - wxLog::OnLog(wxLOG_##level, s_szBuf, time(NULL)); \ - } \ +#define IMPLEMENT_LOG_FUNCTION(level) \ + void wxLog##level(const wxChar *szFormat, ...) \ + { \ + if ( IsLoggingEnabled() ) { \ + wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); \ + \ + va_list argptr; \ + va_start(argptr, szFormat); \ + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); \ + va_end(argptr); \ + \ + wxLog::OnLog(wxLOG_##level, s_szBuf, time(NULL)); \ + } \ } IMPLEMENT_LOG_FUNCTION(FatalError) @@ -143,41 +164,41 @@ IMPLEMENT_LOG_FUNCTION(Status) // same as info, but only if 'verbose' mode is on void wxLogVerbose(const wxChar *szFormat, ...) { - wxLog *pLog = wxLog::GetActiveTarget(); - if ( pLog != NULL && pLog->GetVerbose() ) { - wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); + if ( IsLoggingEnabled() ) { + wxLog *pLog = wxLog::GetActiveTarget(); + if ( pLog != NULL && pLog->GetVerbose() ) { + wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); - va_list argptr; - va_start(argptr, szFormat); - wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); - va_end(argptr); + va_list argptr; + va_start(argptr, szFormat); + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); + va_end(argptr); - wxLog::OnLog(wxLOG_Info, s_szBuf, time(NULL)); - } + wxLog::OnLog(wxLOG_Info, s_szBuf, time(NULL)); + } + } } // debug functions #ifdef __WXDEBUG__ -#define IMPLEMENT_LOG_DEBUG_FUNCTION(level) \ - void wxLog##level(const wxChar *szFormat, ...) \ - { \ - if ( wxLog::GetActiveTarget() != NULL ) { \ - wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); \ - \ - va_list argptr; \ - va_start(argptr, szFormat); \ - wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); \ - va_end(argptr); \ - \ - wxLog::OnLog(wxLOG_##level, s_szBuf, time(NULL)); \ - } \ +#define IMPLEMENT_LOG_DEBUG_FUNCTION(level) \ + void wxLog##level(const wxChar *szFormat, ...) \ + { \ + if ( IsLoggingEnabled() ) { \ + wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); \ + \ + va_list argptr; \ + va_start(argptr, szFormat); \ + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); \ + va_end(argptr); \ + \ + wxLog::OnLog(wxLOG_##level, s_szBuf, time(NULL)); \ + } \ } void wxLogTrace(const wxChar *mask, const wxChar *szFormat, ...) { - wxLog *pLog = wxLog::GetActiveTarget(); - - if ( pLog != NULL && wxLog::IsAllowedTraceMask(mask) ) { + if ( IsLoggingEnabled() && wxLog::IsAllowedTraceMask(mask) ) { wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); wxChar *p = s_szBuf; @@ -205,12 +226,10 @@ void wxLogVerbose(const wxChar *szFormat, ...) void wxLogTrace(wxTraceMask mask, const wxChar *szFormat, ...) { - wxLog *pLog = wxLog::GetActiveTarget(); - // we check that all of mask bits are set in the current mask, so // that wxLogTrace(wxTraceRefCount | wxTraceOle) will only do something // if both bits are set. - if ( pLog != NULL && ((pLog->GetTraceMask() & mask) == mask) ) { + if ( IsLoggingEnabled() && ((wxLog::GetTraceMask() & mask) == mask) ) { wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); va_list argptr; @@ -245,26 +264,30 @@ void wxLogSysErrorHelper(long lErrCode) void WXDLLEXPORT wxLogSysError(const wxChar *szFormat, ...) { - wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); + if ( IsLoggingEnabled() ) { + wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); - va_list argptr; - va_start(argptr, szFormat); - wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); - va_end(argptr); + va_list argptr; + va_start(argptr, szFormat); + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); + va_end(argptr); - wxLogSysErrorHelper(wxSysErrorCode()); + wxLogSysErrorHelper(wxSysErrorCode()); + } } void WXDLLEXPORT wxLogSysError(long lErrCode, const wxChar *szFormat, ...) { - wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); + if ( IsLoggingEnabled() ) { + wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); - va_list argptr; - va_start(argptr, szFormat); - wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); - va_end(argptr); + va_list argptr; + va_start(argptr, szFormat); + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); + va_end(argptr); - wxLogSysErrorHelper(lErrCode); + wxLogSysErrorHelper(lErrCode); + } } // ---------------------------------------------------------------------------- diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp index 59f3a09ffb..1e8541a0b0 100644 --- a/src/common/wincmn.cpp +++ b/src/common/wincmn.cpp @@ -127,14 +127,12 @@ void wxWindowBase::InitBase() #endif // wxUSE_VALIDATORS // use the system default colours - wxSystemSettings settings; - - m_backgroundColour = settings.GetSystemColour(wxSYS_COLOUR_BTNFACE); - // m_foregroundColour = *wxBLACK; // TODO take this from sys settings too? + m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE); m_foregroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT); // GRG, changed Mar/2000 - m_font = settings.GetSystemFont(wxSYS_DEFAULT_GUI_FONT); + m_font = wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT); + // no style bits m_exStyle = m_windowStyle = 0; diff --git a/src/msw/regconf.cpp b/src/msw/regconf.cpp index 9c77482ec9..34a60f02bd 100644 --- a/src/msw/regconf.cpp +++ b/src/msw/regconf.cpp @@ -112,14 +112,28 @@ wxRegConfig::wxRegConfig(const wxString& appName, const wxString& vendorName, //else: we don't need to do all the complicated stuff above wxString str = strLocal.IsEmpty() ? strRoot : strLocal; + + // as we're going to change the name of these keys fairly often and as + // there are only few of wxRegConfig objects (usually 1), we can allow + // ourselves to be generous and spend some memory to significantly improve + // performance of SetPath() + static const size_t MEMORY_PREALLOC = 512; + + m_keyLocalRoot.ReserveMemoryForName(MEMORY_PREALLOC); + m_keyLocal.ReserveMemoryForName(MEMORY_PREALLOC); + m_keyLocalRoot.SetName(wxRegKey::HKCU, SOFTWARE_KEY + str); - m_keyLocal.SetName(m_keyLocalRoot, ""); + m_keyLocal.SetName(m_keyLocalRoot, _T("")); if ( bDoUseGlobal ) { str = strGlobal.IsEmpty() ? strRoot : strGlobal; + + m_keyGlobalRoot.ReserveMemoryForName(MEMORY_PREALLOC); + m_keyGlobal.ReserveMemoryForName(MEMORY_PREALLOC); + m_keyGlobalRoot.SetName(wxRegKey::HKLM, SOFTWARE_KEY + str); - m_keyGlobal.SetName(m_keyGlobalRoot, ""); + m_keyGlobal.SetName(m_keyGlobalRoot, _T("")); } // Create() will Open() if key already exists @@ -146,50 +160,222 @@ wxRegConfig::~wxRegConfig() // ---------------------------------------------------------------------------- // path management // ---------------------------------------------------------------------------- + +// this function is called a *lot* of times (as I learned after seeing from +// profiler output that it is called ~12000 times from Mahogany start up code!) +// so it is important to optimize it - in particular, avoid using generic +// string functions here and do everything manually because it is faster +// +// I still kept the old version to be able to check that the optimized code has +// the same output as the non optimized version. void wxRegConfig::SetPath(const wxString& strPath) { - wxArrayString aParts; + // remember the old path + wxString strOldPath = m_strPath; - // because GetPath() returns "" when we're at root, we must understand - // empty string as "/" - if ( strPath.IsEmpty() || (strPath[0] == wxCONFIG_PATH_SEPARATOR) ) { - // absolute path - wxSplitPath(aParts, strPath); - } - else { - // relative path, combine with current one - wxString strFullPath = GetPath(); - strFullPath << wxCONFIG_PATH_SEPARATOR << strPath; - wxSplitPath(aParts, strFullPath); - } +#ifdef WX_DEBUG_SET_PATH // non optimized version kept here for testing + wxString m_strPathAlt; - // recombine path parts in one variable - wxString strOldPath = m_strPath, strRegPath; - m_strPath.Empty(); - for ( size_t n = 0; n < aParts.Count(); n++ ) { - strRegPath << '\\' << aParts[n]; - m_strPath << wxCONFIG_PATH_SEPARATOR << aParts[n]; - } + { + wxArrayString aParts; + + // because GetPath() returns "" when we're at root, we must understand + // empty string as "/" + if ( strPath.IsEmpty() || (strPath[0] == wxCONFIG_PATH_SEPARATOR) ) { + // absolute path + wxSplitPath(aParts, strPath); + } + else { + // relative path, combine with current one + wxString strFullPath = GetPath(); + strFullPath << wxCONFIG_PATH_SEPARATOR << strPath; + wxSplitPath(aParts, strFullPath); + } + + // recombine path parts in one variable + wxString strRegPath; + m_strPathAlt.Empty(); + for ( size_t n = 0; n < aParts.Count(); n++ ) { + strRegPath << '\\' << aParts[n]; + m_strPathAlt << wxCONFIG_PATH_SEPARATOR << aParts[n]; + } + } +#endif // 0 - if ( m_strPath == strOldPath ) - return; + // check for the most common case first + if ( strPath.empty() ) + { + m_strPath = wxCONFIG_PATH_SEPARATOR; + } + else // not root + { + // construct the full path + wxString strFullPath; + if ( strPath[0u] == wxCONFIG_PATH_SEPARATOR ) + { + // absolute path + strFullPath = strPath; + } + else // relative path + { + strFullPath.reserve(2*m_strPath.length()); + + strFullPath << m_strPath << wxCONFIG_PATH_SEPARATOR << strPath; + } + + // simplify it: we need to handle ".." here + + // count the total number of slashes we have to know if we can go upper + size_t totalSlashes = 0; + + // position of the last slash to be able to backtrack to it quickly if + // needed, but we set it to -1 if we don't have a valid position + // + // we only remember the last position which means that we handle ".." + // quite efficiently but not "../.." - however the latter should be + // much more rare, so it is probably ok + int posLastSlash = -1; + + const wxChar *src = strFullPath.c_str(); + size_t len = strFullPath.length(); + const wxChar *end = src + len; + + wxChar *dst = m_strPath.GetWriteBuf(len); + wxChar *start = dst; + + for ( ; src < end; src++, dst++ ) + { + if ( *src == wxCONFIG_PATH_SEPARATOR ) + { + // check for "/.." + + // note that we don't have to check for src < end here as + // *end == 0 so can't be '.' + if ( src[1] == _T('.') && src[2] == _T('.') && + (src + 3 == end || src[3] == wxCONFIG_PATH_SEPARATOR) ) + { + if ( !totalSlashes ) + { + wxLogWarning(_("'%s' has extra '..', ignored."), + strFullPath.c_str()); + } + else // return to the previous path component + { + // do we already have its position? + if ( posLastSlash == -1 ) + { + // no, find it: note that we are sure to have one + // because totalSlashes > 0 so we don't have to + // check the boundary condition below + + // this is more efficient than strrchr() + while ( *dst != wxCONFIG_PATH_SEPARATOR ) + { + dst--; + } + } + else // the position of last slash was stored + { + // go directly there + dst = start + posLastSlash; + + // invalidate posLastSlash + posLastSlash = -1; + } + + // this shouldn't happen + wxASSERT_MSG( *dst == wxCONFIG_PATH_SEPARATOR, + _T("error in wxRegConfig::SetPath") ); + + // we killed one + totalSlashes--; + } + + // skip both dots + src += 2; + } + else // not "/.." + { + if ( (dst == start) || (dst[-1] != wxCONFIG_PATH_SEPARATOR) ) + { + *dst = wxCONFIG_PATH_SEPARATOR; + + posLastSlash = dst - start; + + totalSlashes++; + } + //else: nothing to do, we squeeze several subseuquent + // slashes into one + } + } + else // normal character + { + // just copy + *dst = *src; + } + } + + // NUL terminate the string + if ( dst[-1] == wxCONFIG_PATH_SEPARATOR && (dst != start + 1) ) + { + // if it has a trailing slash we remove it unless it is the only + // string character + dst--; + } + + *dst = _T('\0'); + + m_strPath.UngetWriteBuf(dst - start); + } - // as we create the registry key when SetPath(key) is done, we can be left - // with plenty of empty keys if this was only done to try to read some value - // which, in fact, doesn't exist - to prevent this from happening we - // automatically delete the old key if it was empty - if ( m_keyLocal.IsEmpty() ) - { - m_keyLocal.DeleteSelf(); - } +#ifdef WX_DEBUG_SET_PATH + wxASSERT( m_strPath == m_strPathAlt ); +#endif + + if ( m_strPath == strOldPath ) + return; + + // registry APIs want backslashes instead of slashes + wxString strRegPath; + size_t len = m_strPath.length(); - // change current key(s) - m_keyLocal.SetName(m_keyLocalRoot, strRegPath); - m_keyGlobal.SetName(m_keyGlobalRoot, strRegPath); - m_keyLocal.Create(); + const wxChar *src = m_strPath.c_str(); + wxChar *dst = strRegPath.GetWriteBuf(len); + + const wxChar *end = src + len; + for ( ; src < end; src++, dst++ ) + { + if ( *src == wxCONFIG_PATH_SEPARATOR ) + *dst = _T('\\'); + else + *dst = *src; + } + + strRegPath.UngetWriteBuf(len); + + // this is not needed any longer as we don't create keys unnecessarily any + // more (now it is done on demand, i.e. only when they're going to contain + // something) +#if 0 + // as we create the registry key when SetPath(key) is done, we can be left + // with plenty of empty keys if this was only done to try to read some + // value which, in fact, doesn't exist - to prevent this from happening we + // automatically delete the old key if it was empty + if ( m_keyLocal.Exists() && LocalKey().IsEmpty() ) + { + m_keyLocal.DeleteSelf(); + } +#endif // 0 - wxLogNull nolog; - m_keyGlobal.Open(); + // change current key(s) + m_keyLocal.SetName(m_keyLocalRoot, strRegPath); + m_keyGlobal.SetName(m_keyGlobalRoot, strRegPath); + + // don't create it right now, wait until it is accessed + //m_keyLocal.Create(); + + wxLogNull nolog; + m_keyGlobal.Open(); } // ---------------------------------------------------------------------------- @@ -219,7 +405,7 @@ bool wxRegConfig::GetNextGroup(wxString& str, long& lIndex) const if ( m_keyGlobal.IsOpened() && !IS_LOCAL_INDEX(lIndex) ) { // try to find a global entry which doesn't appear locally while ( m_keyGlobal.GetNextKey(str, lIndex) ) { - if ( !m_keyLocal.HasSubKey(str) ) { + if ( !m_keyLocal.Exists() || !LocalKey().HasSubKey(str) ) { // ok, found one - return it return TRUE; } @@ -229,10 +415,14 @@ bool wxRegConfig::GetNextGroup(wxString& str, long& lIndex) const lIndex |= LOCAL_MASK; } + // if we don't have the key at all, don't try to enumerate anything under it + if ( !m_keyLocal.Exists() ) + return FALSE; + // much easier with local entries: get the next one we find // (don't forget to clear our flag bit and set it again later) lIndex &= ~LOCAL_MASK; - bool bOk = m_keyLocal.GetNextKey(str, lIndex); + bool bOk = LocalKey().GetNextKey(str, lIndex); lIndex |= LOCAL_MASK; return bOk; @@ -250,7 +440,7 @@ bool wxRegConfig::GetNextEntry(wxString& str, long& lIndex) const if ( m_keyGlobal.IsOpened() && !IS_LOCAL_INDEX(lIndex) ) { // try to find a global entry which doesn't appear locally while ( m_keyGlobal.GetNextValue(str, lIndex) ) { - if ( !m_keyLocal.HasValue(str) ) { + if ( !m_keyLocal.Exists() || !LocalKey().HasValue(str) ) { // ok, found one - return it return TRUE; } @@ -260,10 +450,14 @@ bool wxRegConfig::GetNextEntry(wxString& str, long& lIndex) const lIndex |= LOCAL_MASK; } + // if we don't have the key at all, don't try to enumerate anything under it + if ( !m_keyLocal.Exists() ) + return FALSE; + // much easier with local entries: get the next one we find // (don't forget to clear our flag bit and set it again later) lIndex &= ~LOCAL_MASK; - bool bOk = m_keyLocal.GetNextValue(str, lIndex); + bool bOk = LocalKey().GetNextValue(str, lIndex); lIndex |= LOCAL_MASK; return bOk; @@ -313,7 +507,8 @@ bool wxRegConfig::HasGroup(const wxString& key) const wxString strName(path.Name()); - return m_keyLocal.HasSubKey(strName) || m_keyGlobal.HasSubKey(strName); + return (m_keyLocal.Exists() && LocalKey().HasSubKey(strName)) || + m_keyGlobal.HasSubKey(strName); } bool wxRegConfig::HasEntry(const wxString& key) const @@ -322,7 +517,8 @@ bool wxRegConfig::HasEntry(const wxString& key) const wxString strName(path.Name()); - return m_keyLocal.HasValue(strName) || m_keyGlobal.HasValue(strName); + return (m_keyLocal.Exists() && LocalKey().HasValue(strName)) || + m_keyGlobal.HasValue(strName); } wxConfigBase::EntryType wxRegConfig::GetEntryType(const wxString& key) const @@ -332,7 +528,7 @@ wxConfigBase::EntryType wxRegConfig::GetEntryType(const wxString& key) const wxString strName(path.Name()); bool isNumeric; - if ( m_keyLocal.HasValue(strName) ) + if ( m_keyLocal.Exists() && LocalKey().HasValue(strName) ) isNumeric = m_keyLocal.IsNumericValue(strName); else if ( m_keyGlobal.HasValue(strName) ) isNumeric = m_keyGlobal.IsNumericValue(strName); @@ -356,7 +552,7 @@ bool wxRegConfig::Read(const wxString& key, wxString *pStr) const // overriden by the local key with the same name if ( IsImmutable(path.Name()) ) { if ( TryGetValue(m_keyGlobal, path.Name(), *pStr) ) { - if ( m_keyLocal.HasValue(path.Name()) ) { + if ( m_keyLocal.Exists() && LocalKey().HasValue(path.Name()) ) { wxLogWarning(wxT("User value for immutable key '%s' ignored."), path.Name().c_str()); } @@ -370,7 +566,7 @@ bool wxRegConfig::Read(const wxString& key, wxString *pStr) const } // first try local key - if ( TryGetValue(m_keyLocal, path.Name(), *pStr) || + if ( (m_keyLocal.Exists() && TryGetValue(LocalKey(), path.Name(), *pStr)) || (bQueryGlobal && TryGetValue(m_keyGlobal, path.Name(), *pStr)) ) { // nothing to do @@ -392,7 +588,7 @@ bool wxRegConfig::Read(const wxString& key, wxString *pStr, // overriden by the local key with the same name if ( IsImmutable(path.Name()) ) { if ( TryGetValue(m_keyGlobal, path.Name(), *pStr) ) { - if ( m_keyLocal.HasValue(path.Name()) ) { + if ( m_keyLocal.Exists() && LocalKey().HasValue(path.Name()) ) { wxLogWarning(wxT("User value for immutable key '%s' ignored."), path.Name().c_str()); } @@ -406,7 +602,7 @@ bool wxRegConfig::Read(const wxString& key, wxString *pStr, } // first try local key - if ( TryGetValue(m_keyLocal, path.Name(), *pStr) || + if ( (m_keyLocal.Exists() && TryGetValue(LocalKey(), path.Name(), *pStr)) || (bQueryGlobal && TryGetValue(m_keyGlobal, path.Name(), *pStr)) ) { *pStr = wxConfigBase::ExpandEnvVars(*pStr); return TRUE; @@ -435,7 +631,7 @@ bool wxRegConfig::Read(const wxString& key, long *plResult) const // overriden by the local key with the same name if ( IsImmutable(path.Name()) ) { if ( TryGetValue(m_keyGlobal, path.Name(), plResult) ) { - if ( m_keyLocal.HasValue(path.Name()) ) { + if ( m_keyLocal.Exists() && LocalKey().HasValue(path.Name()) ) { wxLogWarning(wxT("User value for immutable key '%s' ignored."), path.Name().c_str()); } @@ -449,7 +645,7 @@ bool wxRegConfig::Read(const wxString& key, long *plResult) const } // first try local key - if ( TryGetValue(m_keyLocal, path.Name(), plResult) || + if ( (m_keyLocal.Exists() && TryGetValue(LocalKey(), path.Name(), plResult)) || (bQueryGlobal && TryGetValue(m_keyGlobal, path.Name(), plResult)) ) { return TRUE; } @@ -465,7 +661,7 @@ bool wxRegConfig::Write(const wxString& key, const wxString& szValue) return FALSE; } - return m_keyLocal.SetValue(path.Name(), szValue); + return LocalKey().SetValue(path.Name(), szValue); } bool wxRegConfig::Write(const wxString& key, long lValue) @@ -477,7 +673,7 @@ bool wxRegConfig::Write(const wxString& key, long lValue) return FALSE; } - return m_keyLocal.SetValue(path.Name(), lValue); + return LocalKey().SetValue(path.Name(), lValue); } // ---------------------------------------------------------------------------- @@ -548,13 +744,15 @@ bool wxRegConfig::DeleteEntry(const wxString& value, bool bGroupIfEmptyAlso) { wxConfigPathChanger path(this, value); - if ( !m_keyLocal.DeleteValue(path.Name()) ) - return FALSE; + if ( m_keyLocal.Exists() ) { + if ( !m_keyLocal.DeleteValue(path.Name()) ) + return FALSE; - if ( m_keyLocal.IsEmpty() ) { - wxString strKey = GetPath().AfterLast(wxCONFIG_PATH_SEPARATOR); - SetPath(".."); // changes m_keyLocal - return m_keyLocal.DeleteKey(strKey); + if ( m_keyLocal.IsEmpty() ) { + wxString strKey = GetPath().AfterLast(wxCONFIG_PATH_SEPARATOR); + SetPath(".."); // changes m_keyLocal + return LocalKey().DeleteKey(strKey); + } } return TRUE; @@ -564,7 +762,7 @@ bool wxRegConfig::DeleteGroup(const wxString& key) { wxConfigPathChanger path(this, key); - return m_keyLocal.DeleteKey(path.Name()); + return m_keyLocal.Exists() ? LocalKey().DeleteKey(path.Name()) : TRUE; } bool wxRegConfig::DeleteAll() diff --git a/src/msw/registry.cpp b/src/msw/registry.cpp index 978d7ee4fa..b0c061c1d0 100644 --- a/src/msw/registry.cpp +++ b/src/msw/registry.cpp @@ -91,12 +91,12 @@ aStdKeys[] = // ---------------------------------------------------------------------------- // macros // ---------------------------------------------------------------------------- -// @ const_cast<> is not yet supported by all compilers + +// const_cast<> is not yet supported by all compilers #define CONST_CAST ((wxRegKey *)this)-> -#if !USE_MUTABLE - #define m_dwLastError CONST_CAST m_dwLastError -#endif +// and neither is mutable which m_dwLastError should be +#define m_dwLastError CONST_CAST m_dwLastError // ---------------------------------------------------------------------------- // non member functions @@ -186,16 +186,16 @@ wxRegKey::StdKey wxRegKey::GetStdKeyFromHkey(WXHKEY hkey) wxRegKey::wxRegKey() { - m_hKey = 0; m_hRootKey = (WXHKEY) aStdKeys[HKCR].hkey; - m_dwLastError = 0; + + Init(); } wxRegKey::wxRegKey(const wxString& strKey) : m_strKey(strKey) { m_hRootKey = (WXHKEY) aStdKeys[ExtractKeyName(m_strKey)].hkey; - m_hKey = (WXHKEY) NULL; - m_dwLastError = 0; + + Init(); } // parent is a predefined (and preopened) key @@ -203,8 +203,8 @@ wxRegKey::wxRegKey(StdKey keyParent, const wxString& strKey) : m_strKey(strKey) { RemoveTrailingSeparator(m_strKey); m_hRootKey = (WXHKEY) aStdKeys[keyParent].hkey; - m_hKey = (WXHKEY) NULL; - m_dwLastError = 0; + + Init(); } // parent is a normal regkey @@ -221,8 +221,8 @@ wxRegKey::wxRegKey(const wxRegKey& keyParent, const wxString& strKey) RemoveTrailingSeparator(m_strKey); m_hRootKey = keyParent.m_hRootKey; - m_hKey = (WXHKEY) NULL; - m_dwLastError = 0; + + Init(); } // dtor closes the key releasing system resource @@ -260,7 +260,14 @@ void wxRegKey::SetName(const wxRegKey& keyParent, const wxString& strKey) Close(); // combine our name with parent's to get the full name - m_strKey = keyParent.m_strKey; + + // NB: this method is called by wxRegConfig::SetPath() which is a performance + // critical function and so it preallocates space for our m_strKey to + // gain some speed - this is why we only use += here and not = which + // would just free the prealloc'd buffer and would have to realloc it the + // next line! + m_strKey.clear(); + m_strKey += keyParent.m_strKey; if ( !strKey.IsEmpty() && strKey[0] != REG_SEPARATOR ) m_strKey += REG_SEPARATOR; m_strKey += strKey; @@ -408,16 +415,14 @@ bool wxRegKey::Close() { if ( IsOpened() ) { m_dwLastError = RegCloseKey((HKEY) m_hKey); + m_hKey = 0; + if ( m_dwLastError != ERROR_SUCCESS ) { wxLogSysError(m_dwLastError, _("Can't close registry key '%s'"), GetName().c_str()); - m_hKey = 0; return FALSE; } - else { - m_hKey = 0; - } } return TRUE; diff --git a/src/msw/utils.cpp b/src/msw/utils.cpp index f5217d22f9..b7a6ae1a48 100644 --- a/src/msw/utils.cpp +++ b/src/msw/utils.cpp @@ -990,10 +990,22 @@ void wxGetMousePosition( int* x, int* y ) // Return TRUE if we have a colour display bool wxColourDisplay() { - ScreenHDC dc; - int noCols = GetDeviceCaps(dc, NUMCOLORS); + // this function is called from wxDC ctor so it is called a *lot* of times + // hence we optimize it a bit but doign the check only once + // + // this should be MT safe as only the GUI thread (holding the GUI mutex) + // can call us + static int s_isColour = -1; + + if ( s_isColour == -1 ) + { + ScreenHDC dc; + int noCols = ::GetDeviceCaps(dc, NUMCOLORS); + + s_isColour = (noCols == -1) || (noCols > 2); + } - return (noCols == -1) || (noCols > 2); + return s_isColour != 0; } // Returns depth of screen -- 2.45.2