From 02569ba8eb3fbb43b136cc417ecf0ee774ae6205 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 2 Aug 1998 23:12:37 +0000 Subject: [PATCH] wxIniConfig added (pre-alpha quality, many functions not implemented), some bug fixes in wxRegConfig/wxRegKey git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@416 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/msw/iniconf.cpp | 426 +++++++++++++++++++++++++++++++++++++++++++ src/msw/regconf.cpp | 32 ++-- src/msw/registry.cpp | 66 +++++-- 3 files changed, 494 insertions(+), 30 deletions(-) create mode 100644 src/msw/iniconf.cpp diff --git a/src/msw/iniconf.cpp b/src/msw/iniconf.cpp new file mode 100644 index 0000000000..18a824f274 --- /dev/null +++ b/src/msw/iniconf.cpp @@ -0,0 +1,426 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: src/msw/iniconf.cpp +// Purpose: implementation of wxIniConfig class +// Author: Vadim Zeitlin +// Modified by: +// Created: 27.07.98 +// RCS-ID: $Id$ +// Copyright: (c) 1998 Vadim Zeitlin +// Licence: wxWindows license +/////////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif //__BORLANDC__ + +#ifndef WX_PRECOMP + #include + #include +#endif //WX_PRECOMP + +#include +#include +#include + +#include + +// _WINDOWS_ is defined when windows.h is included, +// __WXMSW__ is defined for MS Windows compilation +#if defined(__WXMSW__) && !defined(_WINDOWS_) + #include +#endif //windows.h + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// we replace all path separators with this character +#define PATH_SEP_REPLACE '_' + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// ctor & dtor +// ---------------------------------------------------------------------------- + +wxIniConfig::wxIniConfig(const wxString& strAppName, const wxString& strVendor) + : m_strAppName(strAppName), m_strVendor(strVendor) +{ + if ( strVendor.IsEmpty() ) + m_strVendor = strAppName; + + // append the extension if none given and it's not an absolute file name + // (otherwise we assume that they know what they're doing) + if ( !wxIsPathSeparator(m_strAppName[0u]) && + m_strAppName.Find('.') == NOT_FOUND ) { + m_strAppName << ".ini"; + } + + // set root path + SetPath(""); +} + +wxIniConfig::~wxIniConfig() +{ +} + +// ---------------------------------------------------------------------------- +// path management +// ---------------------------------------------------------------------------- + +void wxIniConfig::SetPath(const wxString& strPath) +{ + wxArrayString aParts; + + if ( strPath.IsEmpty() ) { + // nothing + } + else if ( strPath[0u] == 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); + } + + uint nPartsCount = aParts.Count(); + m_strPath.Empty(); + if ( nPartsCount == 0 ) { + // go to the root + m_strGroup = PATH_SEP_REPLACE; + } + else { + // translate + m_strGroup = aParts[0u]; + for ( uint nPart = 1; nPart < nPartsCount; nPart++ ) { + if ( nPart > 1 ) + m_strPath << PATH_SEP_REPLACE; + m_strPath << aParts[nPart]; + } + } + + // other functions assume that all this is true, i.e. there are no trailing + // underscores at the end except if the group is the root one + wxASSERT( (m_strPath.IsEmpty() || m_strPath.Last() != PATH_SEP_REPLACE) && + (m_strGroup == PATH_SEP_REPLACE || + m_strGroup.Last() != PATH_SEP_REPLACE) ); +} + +const wxString& wxIniConfig::GetPath() const +{ + static wxString s_str; + + // always return abs path + s_str = wxCONFIG_PATH_SEPARATOR; + + if ( m_strGroup == PATH_SEP_REPLACE ) { + // we're at the root level, nothing to do + } + else { + s_str << m_strGroup; + if ( !m_strPath.IsEmpty() ) + s_str << wxCONFIG_PATH_SEPARATOR; + for ( const char *p = m_strPath; *p != '\0'; p++ ) { + s_str << (*p == PATH_SEP_REPLACE ? wxCONFIG_PATH_SEPARATOR : *p); + } + } + + return s_str; +} + +wxString wxIniConfig::GetPrivateKeyName(const char *szKey) const +{ + wxString strKey; + + if ( !m_strPath.IsEmpty() ) + strKey << m_strPath << PATH_SEP_REPLACE; + + strKey << szKey; + + return strKey; +} + +wxString wxIniConfig::GetKeyName(const char *szKey) const +{ + wxString strKey; + + if ( m_strGroup != PATH_SEP_REPLACE ) + strKey << m_strGroup << PATH_SEP_REPLACE; + if ( !m_strPath.IsEmpty() ) + strKey << m_strPath << PATH_SEP_REPLACE; + + strKey << szKey; + + return strKey; +} + +// ---------------------------------------------------------------------------- +// enumeration +// ---------------------------------------------------------------------------- + +// not implemented +bool wxIniConfig::GetFirstGroup(wxString& str, long& lIndex) const +{ + wxFAIL_MSG("not implemented"); + + return FALSE; +} + +bool wxIniConfig::GetNextGroup (wxString& str, long& lIndex) const +{ + wxFAIL_MSG("not implemented"); + + return FALSE; +} + +bool wxIniConfig::GetFirstEntry(wxString& str, long& lIndex) const +{ + wxFAIL_MSG("not implemented"); + + return FALSE; +} + +bool wxIniConfig::GetNextEntry (wxString& str, long& lIndex) const +{ + wxFAIL_MSG("not implemented"); + + return FALSE; +} + +// ---------------------------------------------------------------------------- +// misc info +// ---------------------------------------------------------------------------- + +// not implemented +uint wxIniConfig::GetNumberOfEntries(bool bRecursive) const +{ + wxFAIL_MSG("not implemented"); + + return (uint)-1; +} + +uint wxIniConfig::GetNumberOfGroups(bool bRecursive) const +{ + wxFAIL_MSG("not implemented"); + + return (uint)-1; +} + +bool wxIniConfig::HasGroup(const wxString& strName) const +{ + wxFAIL_MSG("not implemented"); + + return FALSE; +} + +bool wxIniConfig::HasEntry(const wxString& strName) const +{ + wxFAIL_MSG("not implemented"); + + return FALSE; +} + +// is current group empty? +bool wxIniConfig::IsEmpty() const +{ + char szBuf[1024]; + + GetPrivateProfileString(m_strGroup, NULL, "", + szBuf, WXSIZEOF(szBuf), m_strAppName); + if ( !::IsEmpty(szBuf) ) + return FALSE; + + GetProfileString(m_strGroup, NULL, "", szBuf, WXSIZEOF(szBuf)); + if ( !::IsEmpty(szBuf) ) + return FALSE; + + return TRUE; +} + +// ---------------------------------------------------------------------------- +// read/write +// ---------------------------------------------------------------------------- + +bool wxIniConfig::Read(wxString *pstr, + const char *szKey, + const char *szDefault) const +{ + PathChanger path(this, szKey); + wxString strKey = GetPrivateKeyName(path.Name()); + + char szBuf[1024]; // @@ should dynamically allocate memory... + + // first look in the private INI file + + // NB: the lpDefault param to GetPrivateProfileString can't be NULL + GetPrivateProfileString(m_strGroup, strKey, "", + szBuf, WXSIZEOF(szBuf), m_strAppName); + if ( ::IsEmpty(szBuf) ) { + // now look in win.ini + wxString strKey = GetKeyName(path.Name()); + GetProfileString(m_strGroup, strKey, "", szBuf, WXSIZEOF(szBuf)); + } + + if ( ::IsEmpty(szBuf) ) { + *pstr = szDefault; + return FALSE; + } + else { + return TRUE; + } +} + +const char *wxIniConfig::Read(const char *szKey, + const char *szDefault) const +{ + static wxString s_str; + Read(&s_str, szKey, szDefault); + + return s_str.c_str(); +} + +bool wxIniConfig::Read(long *pl, const char *szKey, long lDefault) const +{ + PathChanger path(this, szKey); + wxString strKey = GetPrivateKeyName(path.Name()); + + // hack: we have no mean to know if it really found the default value or + // didn't find anything, so we call it twice + + static const int nMagic = 17; // 17 is some "rare" number + static const int nMagic2 = 28; // arbitrary number != nMagic + long lVal = GetPrivateProfileInt(m_strGroup, strKey, nMagic, m_strAppName); + if ( lVal != nMagic ) { + // the value was read from the file + *pl = lVal; + return TRUE; + } + + // is it really nMagic? + lVal = GetPrivateProfileInt(m_strGroup, strKey, nMagic2, m_strAppName); + if ( lVal == nMagic ) { + // the nMagic it returned was indeed read from the file + *pl = lVal; + return TRUE; + } + + // no, it was just returning the default value, so now look in win.ini + *pl = GetProfileInt(m_strVendor, GetKeyName(szKey), lDefault); + + // we're not going to check here whether it read the default or not: it's + // not that important + return TRUE; +} + +long wxIniConfig::Read(const char *szKey, long lDefault) const +{ + long lVal; + Read(&lVal, szKey, lDefault); + + return lVal; +} + +bool wxIniConfig::Write(const char *szKey, const char *szValue) +{ + PathChanger path(this, szKey); + wxString strKey = GetPrivateKeyName(path.Name()); + + bool bOk = WritePrivateProfileString(m_strGroup, strKey, + szValue, m_strAppName) != 0; + + if ( !bOk ) + wxLogLastError("WritePrivateProfileString"); + + return bOk; +} + +bool wxIniConfig::Write(const char *szKey, long lValue) +{ + // ltoa() is not ANSI :-( + char szBuf[40]; // should be good for sizeof(long) <= 16 (128 bits) + sprintf(szBuf, "%ld", lValue); + + return Write(szKey, szBuf); +} + +bool wxIniConfig::Flush(bool /* bCurrentOnly */) +{ + // this is just the way it works + return WritePrivateProfileString(NULL, NULL, NULL, m_strAppName) != 0; +} + +// ---------------------------------------------------------------------------- +// delete +// ---------------------------------------------------------------------------- + +bool wxIniConfig::DeleteEntry(const char *szKey, bool bGroupIfEmptyAlso) +{ + // passing NULL as value to WritePrivateProfileString deletes the key + if ( !Write(szKey, (const char *)NULL) ) + return FALSE; + + if ( !bGroupIfEmptyAlso || !IsEmpty() ) + return TRUE; + + // delete the current group too + bool bOk = WritePrivateProfileString(m_strGroup, NULL, + NULL, m_strAppName) != 0; + + if ( !bOk ) + wxLogLastError("WritePrivateProfileString"); + + return bOk; +} + +bool wxIniConfig::DeleteGroup(const char *szKey) +{ + PathChanger path(this, szKey); + + // passing NULL as section name to WritePrivateProfileString deletes the + // whole section according to the docs + bool bOk = WritePrivateProfileString(path.Name(), NULL, + NULL, m_strAppName) != 0; + + if ( !bOk ) + wxLogLastError("WritePrivateProfileString"); + + return bOk; +} + +bool wxIniConfig::DeleteAll() +{ + // first delete our group in win.ini + WriteProfileString(m_strVendor, NULL, NULL); + + // then delete our own ini file + char szBuf[MAX_PATH]; + uint nRc = GetWindowsDirectory(szBuf, WXSIZEOF(szBuf)); + if ( nRc == 0 ) + wxLogLastError("GetWindowsDirectory"); + else if ( nRc > WXSIZEOF(szBuf) ) + wxFAIL_MSG("buffer is too small for Windows directory."); + + wxString strFile = szBuf; + strFile << '\\' << m_strAppName; + + if ( !DeleteFile(strFile) ) { + wxLogSysError(_("Can't delete the INI file '%s'"), strFile.c_str()); + return FALSE; + } + + return TRUE; +} diff --git a/src/msw/regconf.cpp b/src/msw/regconf.cpp index 749f2798ea..220058f609 100644 --- a/src/msw/regconf.cpp +++ b/src/msw/regconf.cpp @@ -140,13 +140,13 @@ void wxRegConfig::SetPath(const wxString& strPath) #define LOCAL_MASK 0x8000 #define IS_LOCAL_INDEX(l) (((l) & LOCAL_MASK) != 0) -bool wxRegConfig::GetFirstGroup(wxString& str, long& lIndex) +bool wxRegConfig::GetFirstGroup(wxString& str, long& lIndex) const { lIndex = 0; return GetNextGroup(str, lIndex); } -bool wxRegConfig::GetNextGroup(wxString& str, long& lIndex) +bool wxRegConfig::GetNextGroup(wxString& str, long& lIndex) const { // are we already enumerating local entries? if ( m_keyGlobal.IsOpened() && !IS_LOCAL_INDEX(lIndex) ) { @@ -169,13 +169,13 @@ bool wxRegConfig::GetNextGroup(wxString& str, long& lIndex) return bOk; } -bool wxRegConfig::GetFirstEntry(wxString& str, long& lIndex) +bool wxRegConfig::GetFirstEntry(wxString& str, long& lIndex) const { lIndex = 0; return GetNextEntry(str, lIndex); } -bool wxRegConfig::GetNextEntry(wxString& str, long& lIndex) +bool wxRegConfig::GetNextEntry(wxString& str, long& lIndex) const { // are we already enumerating local entries? if ( m_keyGlobal.IsOpened() && !IS_LOCAL_INDEX(lIndex) ) { @@ -250,9 +250,9 @@ bool wxRegConfig::HasEntry(const wxString& strName) const // reading/writing // ---------------------------------------------------------------------------- -bool wxRegConfig::Read(wxString& str, - const char *szKey, - const char *szDefault) const +bool wxRegConfig::Read(wxString *pStr, + const char *szKey, + const char *szDefault) const { PathChanger path(this, szKey); @@ -261,7 +261,7 @@ bool wxRegConfig::Read(wxString& str, // if immutable key exists in global key we must check that it's not // overriden by the local key with the same name if ( IsImmutable(path.Name()) ) { - if ( TryGetValue(m_keyGlobal, path.Name(), str) ) { + if ( TryGetValue(m_keyGlobal, path.Name(), *pStr) ) { if ( m_keyLocal.HasValue(path.Name()) ) { wxLogWarning("User value for immutable key '%s' ignored.", path.Name().c_str()); @@ -276,17 +276,17 @@ bool wxRegConfig::Read(wxString& str, } // first try local key - if ( TryGetValue(m_keyLocal, path.Name(), str) || - (bQueryGlobal && TryGetValue(m_keyGlobal, path.Name(), str)) ) { + if ( TryGetValue(m_keyLocal, path.Name(), *pStr) || + (bQueryGlobal && TryGetValue(m_keyGlobal, path.Name(), *pStr)) ) { return TRUE; } // default value - str = szDefault; + *pStr = szDefault; return FALSE; } -bool wxRegConfig::Read(long &lValue, const char *szKey, long lDefault) const +bool wxRegConfig::Read(long *plResult, const char *szKey, long lDefault) const { PathChanger path(this, szKey); @@ -295,7 +295,7 @@ bool wxRegConfig::Read(long &lValue, const char *szKey, long lDefault) const // if immutable key exists in global key we must check that it's not // overriden by the local key with the same name if ( IsImmutable(path.Name()) ) { - if ( TryGetValue(m_keyGlobal, path.Name(), &lValue) ) { + if ( TryGetValue(m_keyGlobal, path.Name(), plResult) ) { if ( m_keyLocal.HasValue(path.Name()) ) { wxLogWarning("User value for immutable key '%s' ignored.", path.Name().c_str()); @@ -310,13 +310,13 @@ bool wxRegConfig::Read(long &lValue, const char *szKey, long lDefault) const } // first try local key - if ( TryGetValue(m_keyLocal, path.Name(), &lValue) || - (bQueryGlobal && TryGetValue(m_keyGlobal, path.Name(), &lValue)) ) { + if ( TryGetValue(m_keyLocal, path.Name(), plResult) || + (bQueryGlobal && TryGetValue(m_keyGlobal, path.Name(), plResult)) ) { return TRUE; } // default - lValue = lDefault; + *plResult = lDefault; return FALSE; } diff --git a/src/msw/registry.cpp b/src/msw/registry.cpp index c6d0142dc1..f40064ae68 100644 --- a/src/msw/registry.cpp +++ b/src/msw/registry.cpp @@ -256,9 +256,10 @@ void wxRegKey::SetName(const wxRegKey& keyParent, const wxString& strKey) Close(); // combine our name with parent's to get the full name - m_strKey = strKey; + m_strKey = keyParent.m_strKey; if ( !strKey.IsEmpty() && strKey[0] != REG_SEPARATOR ) m_strKey += REG_SEPARATOR; + m_strKey += strKey; RemoveTrailingSeparator(m_strKey); @@ -296,6 +297,42 @@ wxString wxRegKey::GetName(bool bShortPrefix) const return str; } +bool wxRegKey::GetKeyInfo(ulong *pnSubKeys, + ulong *pnMaxKeyLen, + ulong *pnValues, + ulong *pnMaxValueLen) const +{ +#ifdef __WIN32__ + m_dwLastError = ::RegQueryInfoKey + ( + m_hKey, + NULL, // class name + NULL, // (ptr to) size of class name buffer + RESERVED, + pnSubKeys, // [out] number of subkeys + pnMaxKeyLen, // [out] max length of a subkey name + NULL, // longest subkey class name + pnValues, // [out] number of values + pnMaxValueLen, // [out] max length of a value name + NULL, // longest value data + NULL, // security descriptor + NULL // time of last modification + ); + + if ( m_dwLastError != ERROR_SUCCESS ) { + wxLogSysError(m_dwLastError, _("can't get info about registry key '%s'"), + GetName().c_str()); + return FALSE; + } + else + return TRUE; +#else // Win16 + wxFAIL_MSG("GetKeyInfo() not implemented"); + + return FALSE; +#endif +} + // ---------------------------------------------------------------------------- // operations // ---------------------------------------------------------------------------- @@ -308,7 +345,7 @@ bool wxRegKey::Open() m_dwLastError = RegOpenKey(m_hRootKey, m_strKey, &m_hKey); if ( m_dwLastError != ERROR_SUCCESS ) { - wxLogSysError(m_dwLastError, "can't open registry key '%s'", + wxLogSysError(m_dwLastError, _("can't open registry key '%s'"), GetName().c_str()); return FALSE; } @@ -329,7 +366,7 @@ bool wxRegKey::Create(bool bOkIfExists) m_dwLastError = RegCreateKey(m_hRootKey, m_strKey, &m_hKey); if ( m_dwLastError != ERROR_SUCCESS ) { - wxLogSysError(m_dwLastError, "can't create registry key '%s'", + wxLogSysError(m_dwLastError, _("can't create registry key '%s'"), GetName().c_str()); return FALSE; } @@ -343,7 +380,7 @@ bool wxRegKey::Close() if ( IsOpened() ) { m_dwLastError = RegCloseKey(m_hKey); if ( m_dwLastError != ERROR_SUCCESS ) { - wxLogSysError(m_dwLastError, "can't close registry key '%s'", + wxLogSysError(m_dwLastError, _("can't close registry key '%s'"), GetName().c_str()); m_hKey = 0; @@ -395,7 +432,8 @@ bool wxRegKey::DeleteSelf() m_dwLastError = RegDeleteKey(m_hRootKey, m_strKey); if ( m_dwLastError != ERROR_SUCCESS ) { - wxLogSysError(m_dwLastError, "can't delete key '%s'", GetName().c_str()); + wxLogSysError(m_dwLastError, _("can't delete key '%s'"), + GetName().c_str()); return FALSE; } @@ -419,7 +457,7 @@ bool wxRegKey::DeleteValue(const char *szValue) #ifdef __WIN32__ m_dwLastError = RegDeleteValue(m_hKey, szValue); if ( m_dwLastError != ERROR_SUCCESS ) { - wxLogSysError(m_dwLastError, "can't delete value '%s' from key '%s'", + wxLogSysError(m_dwLastError, _("can't delete value '%s' from key '%s'"), szValue, GetName().c_str()); return FALSE; } @@ -430,7 +468,7 @@ bool wxRegKey::DeleteValue(const char *szValue) // just set the (default and unique) value of the key to "" m_dwLastError = RegSetValue(m_hKey, NULL, REG_SZ, "", RESERVED); if ( m_dwLastError != ERROR_SUCCESS ) { - wxLogSysError(m_dwLastError, "can't delete value of key '%s'", + wxLogSysError(m_dwLastError, _("can't delete value of key '%s'"), GetName().c_str()); return FALSE; } @@ -487,7 +525,7 @@ wxRegKey::ValueType wxRegKey::GetValueType(const char *szValue) m_dwLastError = RegQueryValueEx(m_hKey, szValue, RESERVED, &dwType, NULL, NULL); if ( m_dwLastError != ERROR_SUCCESS ) { - wxLogSysError(m_dwLastError, "can't read value of key '%s'", + wxLogSysError(m_dwLastError, _("can't read value of key '%s'"), GetName().c_str()); return Type_None; } @@ -508,7 +546,7 @@ bool wxRegKey::SetValue(const char *szValue, long lValue) return TRUE; } - wxLogSysError(m_dwLastError, "can't set value of '%s'", + wxLogSysError(m_dwLastError, _("can't set value of '%s'"), GetFullName(this, szValue)); return FALSE; } @@ -521,7 +559,7 @@ bool wxRegKey::QueryValue(const char *szValue, long *plValue) const m_dwLastError = RegQueryValueEx(m_hKey, szValue, RESERVED, &dwType, pBuf, &dwSize); if ( m_dwLastError != ERROR_SUCCESS ) { - wxLogSysError(m_dwLastError, "can't read value of key '%s'", + wxLogSysError(m_dwLastError, _("can't read value of key '%s'"), GetName().c_str()); return FALSE; } @@ -569,7 +607,7 @@ bool wxRegKey::QueryValue(const char *szValue, wxString& strValue) const #endif //WIN16/32 } - wxLogSysError(m_dwLastError, "can't read value of '%s'", + wxLogSysError(m_dwLastError, _("can't read value of '%s'"), GetFullName(this, szValue)); return FALSE; } @@ -593,7 +631,7 @@ bool wxRegKey::SetValue(const char *szValue, const wxString& strValue) #endif //WIN16/32 } - wxLogSysError(m_dwLastError, "can't set value of '%s'", + wxLogSysError(m_dwLastError, _("can't set value of '%s'"), GetFullName(this, szValue)); return FALSE; } @@ -646,7 +684,7 @@ bool wxRegKey::GetNextValue(wxString& strValueName, long& lIndex) const lIndex = -1; } else { - wxLogSysError(m_dwLastError, "can't enumerate values of key '%s'", + wxLogSysError(m_dwLastError, _("can't enumerate values of key '%s'"), GetName().c_str()); } @@ -691,7 +729,7 @@ bool wxRegKey::GetNextKey(wxString& strKeyName, long& lIndex) const lIndex = -1; } else { - wxLogSysError(m_dwLastError, "can't enumerate subkeys of key '%s'", + wxLogSysError(m_dwLastError, _("can't enumerate subkeys of key '%s'"), GetName().c_str()); } -- 2.45.2