X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c9f7896861f734ce044ee8601ba2d8a6959c9d9e..291b0f5b14b62be240ae5cb1ec2ade3d8db6a776:/src/common/fileconf.cpp diff --git a/src/common/fileconf.cpp b/src/common/fileconf.cpp index 4662dcccef..bc153a0a9f 100644 --- a/src/common/fileconf.cpp +++ b/src/common/fileconf.cpp @@ -42,9 +42,10 @@ #include "wx/fileconf.h" #include "wx/filefn.h" +#include "wx/stdpaths.h" + #if defined(__WXMAC__) #include "wx/mac/private.h" // includes mac headers - #include "wx/filename.h" // for MacSetTypeAndCreator #endif #if defined(__WXMSW__) @@ -221,12 +222,12 @@ public: bool IsEmpty() const { return Entries().IsEmpty() && Groups().IsEmpty(); } // find entry/subgroup (NULL if not found) - wxFileConfigGroup *FindSubgroup(const wxChar *szName) const; - wxFileConfigEntry *FindEntry (const wxChar *szName) const; + wxFileConfigGroup *FindSubgroup(const wxString& name) const; + wxFileConfigEntry *FindEntry (const wxString& name) const; // delete entry/subgroup, return false if doesn't exist - bool DeleteSubgroupByName(const wxChar *szName); - bool DeleteEntry(const wxChar *szName); + bool DeleteSubgroupByName(const wxString& name); + bool DeleteEntry(const wxString& name); // create new entry/subgroup returning pointer to newly created element wxFileConfigGroup *AddSubgroup(const wxString& strName); @@ -260,118 +261,71 @@ public: // ---------------------------------------------------------------------------- // static functions // ---------------------------------------------------------------------------- -wxString wxFileConfig::GetGlobalDir() -{ - wxString strDir; -#ifdef __VMS__ // Note if __VMS is defined __UNIX is also defined - strDir = wxT("sys$manager:"); -#elif defined(__WXMAC__) - strDir = wxMacFindFolder( (short) kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder ) ; -#elif defined( __UNIX__ ) - strDir = wxT("/etc/"); -#elif defined(__OS2__) - ULONG aulSysInfo[QSV_MAX] = {0}; - UINT drive; - APIRET rc; - - rc = DosQuerySysInfo( 1L, QSV_MAX, (PVOID)aulSysInfo, sizeof(ULONG)*QSV_MAX); - if (rc == 0) +// this function modifies in place the given wxFileName object if it doesn't +// already have an extension +// +// note that it's slightly misnamed under Mac as there it doesn't add an +// extension but modifies the file name instead, so you shouldn't suppose that +// fn.HasExt() is true after it returns +static void AddConfFileExtIfNeeded(wxFileName& fn) +{ + if ( !fn.HasExt() ) { - drive = aulSysInfo[QSV_BOOT_DRIVE - 1]; - strDir.Printf(wxT("%c:\\OS2\\"), 'A'+drive-1); +#if defined( __WXMAC__ ) + fn.SetName(fn.GetName() + wxT(" Preferences")); +#elif defined( __UNIX__ ) + fn.SetExt(wxT(".conf")); +#else // Windows + fn.SetExt(wxT(".ini")); +#endif // UNIX/Win } -#elif defined(__WXSTUBS__) - wxFAIL_MSG( wxT("TODO") ); -#elif defined(__DOS__) - // There's no such thing as global cfg dir in MS-DOS, let's return - // current directory (FIXME_MGL?) - strDir = wxT(".\\"); -#elif defined(__WXWINCE__) - strDir = wxT("\\Windows\\"); -#else // Windows - - wxChar szWinDir[MAX_PATH]; - ::GetWindowsDirectory(szWinDir, MAX_PATH); - - strDir = szWinDir; - strDir << wxT('\\'); -#endif // Unix/Windows - - return strDir; } -wxString wxFileConfig::GetLocalDir() +wxString wxFileConfig::GetGlobalDir() { - wxString strDir; - -#if defined(__WXMAC__) || defined(__DOS__) - // no local dir concept on Mac OS 9 or MS-DOS - strDir << GetGlobalDir() ; -#else - wxGetHomeDir(&strDir); - - #ifdef __UNIX__ - if ( - (strDir.Last() != wxT('/')) - #ifdef __VMS - && (strDir.Last() != wxT(']')) - #endif - ) - strDir << wxT('/'); - #else - if (strDir.Last() != wxT('\\')) - strDir << wxT('\\'); - #endif -#endif - - return strDir; + return wxStandardPaths::Get().GetConfigDir(); } -wxString wxFileConfig::GetGlobalFileName(const wxString& file) +wxString wxFileConfig::GetLocalDir(int style) { - wxString str = GetGlobalDir(); - str << file; + wxUnusedVar(style); - if ( wxStrchr(file, wxT('.')) == NULL ) -#if defined( __WXMAC__ ) - str << wxT(" Preferences") ; -#elif defined( __UNIX__ ) - str << wxT(".conf"); -#else // Windows - str << wxT(".ini"); -#endif // UNIX/Win + wxStandardPathsBase& stdp = wxStandardPaths::Get(); - return str; + // it so happens that user data directory is a subdirectory of user config + // directory on all supported platforms, which explains why we use it here + return style & wxCONFIG_USE_SUBDIR ? stdp.GetUserDataDir() + : stdp.GetUserConfigDir(); } -wxString wxFileConfig::GetLocalFileName(const wxString& file) +wxFileName wxFileConfig::GetGlobalFile(const wxString& szFile) { -#ifdef __VMS__ - // On VMS I saw the problem that the home directory was appended - // twice for the configuration file. Does that also happen for - // other platforms? - wxString str = wxT( '.' ); -#else - wxString str = GetLocalDir(); -#endif + wxFileName fn(GetGlobalDir(), szFile); -#if defined( __UNIX__ ) && !defined( __VMS ) && !defined( __WXMAC__ ) - str << wxT('.'); -#endif + AddConfFileExtIfNeeded(fn); - str << file; + return fn; +} -#if defined(__WINDOWS__) || defined(__DOS__) - if ( wxStrchr(file, wxT('.')) == NULL ) - str << wxT(".ini"); -#endif +wxFileName wxFileConfig::GetLocalFile(const wxString& szFile, int style) +{ + wxFileName fn(GetLocalDir(style), szFile); -#ifdef __WXMAC__ - str << wxT(" Preferences") ; -#endif +#ifdef __UNIX__ + if ( !(style & wxCONFIG_USE_SUBDIR) ) + { + // dot-files under Unix start with, well, a dot (but OTOH they usually + // don't have any specific extension) + fn.SetName(wxT('.') + fn.GetName()); + } + else // we do append ".conf" extension to config files in subdirectories +#endif // __UNIX__ + { + AddConfFileExtIfNeeded(fn); + } - return str; + return fn; } // ---------------------------------------------------------------------------- @@ -390,9 +344,9 @@ void wxFileConfig::Init() // It's not an error if (one of the) file(s) doesn't exist. // parse the global file - if ( !m_strGlobalFile.empty() && wxFile::Exists(m_strGlobalFile) ) + if ( m_fnGlobalFile.IsOk() && m_fnGlobalFile.FileExists() ) { - wxTextFile fileGlobal(m_strGlobalFile); + wxTextFile fileGlobal(m_fnGlobalFile.GetFullPath()); if ( fileGlobal.Open(*m_conv/*ignored in ANSI build*/) ) { @@ -401,14 +355,14 @@ void wxFileConfig::Init() } else { - wxLogWarning(_("can't open global configuration file '%s'."), m_strGlobalFile.c_str()); + wxLogWarning(_("can't open global configuration file '%s'."), m_fnGlobalFile.GetFullPath().c_str()); } } // parse the local file - if ( !m_strLocalFile.empty() && wxFile::Exists(m_strLocalFile) ) + if ( m_fnLocalFile.IsOk() && m_fnLocalFile.FileExists() ) { - wxTextFile fileLocal(m_strLocalFile); + wxTextFile fileLocal(m_fnLocalFile.GetFullPath()); if ( fileLocal.Open(*m_conv/*ignored in ANSI build*/) ) { Parse(fileLocal, true /* local */); @@ -416,7 +370,7 @@ void wxFileConfig::Init() } else { - wxLogWarning(_("can't open user configuration file '%s'."), m_strLocalFile.c_str() ); + wxLogWarning(_("can't open user configuration file '%s'."), m_fnLocalFile.GetFullPath().c_str() ); } } @@ -431,47 +385,34 @@ wxFileConfig::wxFileConfig(const wxString& appName, const wxString& vendorName, : wxConfigBase(::GetAppName(appName), vendorName, strLocal, strGlobal, style), - m_strLocalFile(strLocal), m_strGlobalFile(strGlobal), + m_fnLocalFile(strLocal), + m_fnGlobalFile(strGlobal), m_conv(conv.Clone()) { // Make up names for files if empty - if ( m_strLocalFile.empty() && (style & wxCONFIG_USE_LOCAL_FILE) ) - { - m_strLocalFile = GetLocalFileName(GetAppName()); -#if defined(__UNIX__) && !defined(__VMS) - if ( style & wxCONFIG_USE_SUBDIR ) - m_strLocalFile << wxFILE_SEP_PATH << GetAppName() << _T(".conf"); -#endif - } + if ( !m_fnLocalFile.IsOk() && (style & wxCONFIG_USE_LOCAL_FILE) ) + m_fnLocalFile = GetLocalFile(GetAppName(), style); - if ( m_strGlobalFile.empty() && (style & wxCONFIG_USE_GLOBAL_FILE) ) - m_strGlobalFile = GetGlobalFileName(GetAppName()); + if ( !m_fnGlobalFile.IsOk() && (style & wxCONFIG_USE_GLOBAL_FILE) ) + m_fnGlobalFile = GetGlobalFile(GetAppName()); // Check if styles are not supplied, but filenames are, in which case // add the correct styles. - if ( !m_strLocalFile.empty() ) + if ( m_fnLocalFile.IsOk() ) SetStyle(GetStyle() | wxCONFIG_USE_LOCAL_FILE); - if ( !m_strGlobalFile.empty() ) + if ( m_fnGlobalFile.IsOk() ) SetStyle(GetStyle() | wxCONFIG_USE_GLOBAL_FILE); // if the path is not absolute, prepend the standard directory to it - // UNLESS wxCONFIG_USE_RELATIVE_PATH style is set + // unless explicitly asked not to if ( !(style & wxCONFIG_USE_RELATIVE_PATH) ) { - if ( !m_strLocalFile.empty() && !wxIsAbsolutePath(m_strLocalFile) ) - { - const wxString strLocalOrig = m_strLocalFile; - m_strLocalFile = GetLocalDir(); - m_strLocalFile << strLocalOrig; - } + if ( m_fnLocalFile.IsOk() ) + m_fnLocalFile.MakeAbsolute(GetLocalDir(style)); - if ( !m_strGlobalFile.empty() && !wxIsAbsolutePath(m_strGlobalFile) ) - { - const wxString strGlobalOrig = m_strGlobalFile; - m_strGlobalFile = GetGlobalDir(); - m_strGlobalFile << strGlobalOrig; - } + if ( m_fnGlobalFile.IsOk() ) + m_fnGlobalFile.MakeAbsolute(GetGlobalDir()); } SetUmask(-1); @@ -595,15 +536,16 @@ wxFileConfig::~wxFileConfig() void wxFileConfig::Parse(const wxTextBuffer& buffer, bool bLocal) { - const wxChar *pStart; - const wxChar *pEnd; - wxString strLine; size_t nLineCount = buffer.GetLineCount(); for ( size_t n = 0; n < nLineCount; n++ ) { - strLine = buffer[n]; + wxString strLine = buffer[n]; + // FIXME-UTF8: rewrite using iterators, without this buffer + wxWxCharBuffer buf(strLine.c_str()); + const wxChar *pStart; + const wxChar *pEnd; // add the line to linked list if ( bLocal ) @@ -619,7 +561,7 @@ void wxFileConfig::Parse(const wxTextBuffer& buffer, bool bLocal) // skip leading spaces - for ( pStart = strLine; wxIsspace(*pStart); pStart++ ) + for ( pStart = buf; wxIsspace(*pStart); pStart++ ) ; // skip blank/comment lines @@ -787,7 +729,7 @@ wxFileConfig::DoSetPath(const wxString& strPath, bool createMissingComponents) // change current group size_t n; m_pCurrentGroup = m_pRootGroup; - for ( n = 0; n < aParts.Count(); n++ ) { + for ( n = 0; n < aParts.GetCount(); n++ ) { wxFileConfigGroup *pNextGroup = m_pCurrentGroup->FindSubgroup(aParts[n]); if ( pNextGroup == NULL ) { @@ -802,7 +744,7 @@ wxFileConfig::DoSetPath(const wxString& strPath, bool createMissingComponents) // recombine path parts in one variable m_strPath.Empty(); - for ( n = 0; n < aParts.Count(); n++ ) { + for ( n = 0; n < aParts.GetCount(); n++ ) { m_strPath << wxCONFIG_PATH_SEPARATOR << aParts[n]; } @@ -826,7 +768,7 @@ bool wxFileConfig::GetFirstGroup(wxString& str, long& lIndex) const bool wxFileConfig::GetNextGroup (wxString& str, long& lIndex) const { - if ( size_t(lIndex) < m_pCurrentGroup->Groups().Count() ) { + if ( size_t(lIndex) < m_pCurrentGroup->Groups().GetCount() ) { str = m_pCurrentGroup->Groups()[(size_t)lIndex++]->Name(); return true; } @@ -842,7 +784,7 @@ bool wxFileConfig::GetFirstEntry(wxString& str, long& lIndex) const bool wxFileConfig::GetNextEntry (wxString& str, long& lIndex) const { - if ( size_t(lIndex) < m_pCurrentGroup->Entries().Count() ) { + if ( size_t(lIndex) < m_pCurrentGroup->Entries().GetCount() ) { str = m_pCurrentGroup->Entries()[(size_t)lIndex++]->Name(); return true; } @@ -852,10 +794,10 @@ bool wxFileConfig::GetNextEntry (wxString& str, long& lIndex) const size_t wxFileConfig::GetNumberOfEntries(bool bRecursive) const { - size_t n = m_pCurrentGroup->Entries().Count(); + size_t n = m_pCurrentGroup->Entries().GetCount(); if ( bRecursive ) { wxFileConfigGroup *pOldCurrentGroup = m_pCurrentGroup; - size_t nSubgroups = m_pCurrentGroup->Groups().Count(); + size_t nSubgroups = m_pCurrentGroup->Groups().GetCount(); for ( size_t nGroup = 0; nGroup < nSubgroups; nGroup++ ) { CONST_CAST m_pCurrentGroup = m_pCurrentGroup->Groups()[nGroup]; n += GetNumberOfEntries(true); @@ -868,10 +810,10 @@ size_t wxFileConfig::GetNumberOfEntries(bool bRecursive) const size_t wxFileConfig::GetNumberOfGroups(bool bRecursive) const { - size_t n = m_pCurrentGroup->Groups().Count(); + size_t n = m_pCurrentGroup->Groups().GetCount(); if ( bRecursive ) { wxFileConfigGroup *pOldCurrentGroup = m_pCurrentGroup; - size_t nSubgroups = m_pCurrentGroup->Groups().Count(); + size_t nSubgroups = m_pCurrentGroup->Groups().GetCount(); for ( size_t nGroup = 0; nGroup < nSubgroups; nGroup++ ) { CONST_CAST m_pCurrentGroup = m_pCurrentGroup->Groups()[nGroup]; n += GetNumberOfGroups(true); @@ -1041,13 +983,13 @@ bool wxFileConfig::DoWriteLong(const wxString& key, long lValue) bool wxFileConfig::Flush(bool /* bCurrentOnly */) { - if ( !IsDirty() || !m_strLocalFile ) + if ( !IsDirty() || !m_fnLocalFile.GetFullPath() ) return true; // set the umask if needed wxCHANGE_UMASK(m_umask); - wxTempFile file(m_strLocalFile); + wxTempFile file(m_fnLocalFile.GetFullPath()); if ( !file.IsOpened() ) { @@ -1079,7 +1021,7 @@ bool wxFileConfig::Flush(bool /* bCurrentOnly */) ResetDirty(); #if defined(__WXMAC__) - wxFileName(m_strLocalFile).MacSetTypeAndCreator('TEXT', 'ttxt'); + m_fnLocalFile.MacSetTypeAndCreator('TEXT', 'ttxt'); #endif // __WXMAC__ return true; @@ -1118,7 +1060,7 @@ bool wxFileConfig::Save(wxOutputStream& os, const wxMBConv& conv) bool wxFileConfig::RenameEntry(const wxString& oldName, const wxString& newName) { - wxASSERT_MSG( !wxStrchr(oldName, wxCONFIG_PATH_SEPARATOR), + wxASSERT_MSG( oldName.find(wxCONFIG_PATH_SEPARATOR) == wxString::npos, _T("RenameEntry(): paths are not supported") ); // check that the entry exists @@ -1205,12 +1147,13 @@ bool wxFileConfig::DeleteAll() { CleanUp(); - if ( !m_strLocalFile.empty() ) + if ( m_fnLocalFile.IsOk() ) { - if ( wxFile::Exists(m_strLocalFile) && wxRemove(m_strLocalFile) == -1 ) + if ( m_fnLocalFile.FileExists() && + !wxRemoveFile(m_fnLocalFile.GetFullPath()) ) { wxLogSysError(_("can't delete user configuration file '%s'"), - m_strLocalFile.c_str()); + m_fnLocalFile.GetFullPath().c_str()); return false; } } @@ -1398,12 +1341,12 @@ wxFileConfigGroup::wxFileConfigGroup(wxFileConfigGroup *pParent, wxFileConfigGroup::~wxFileConfigGroup() { // entries - size_t n, nCount = m_aEntries.Count(); + size_t n, nCount = m_aEntries.GetCount(); for ( n = 0; n < nCount; n++ ) delete m_aEntries[n]; // subgroups - nCount = m_aSubgroups.Count(); + nCount = m_aSubgroups.GetCount(); for ( n = 0; n < nCount; n++ ) delete m_aSubgroups[n]; } @@ -1566,7 +1509,7 @@ void wxFileConfigGroup::UpdateGroupAndSubgroupsLines() // also update all subgroups as they have this groups name in their lines - const size_t nCount = m_aSubgroups.Count(); + const size_t nCount = m_aSubgroups.GetCount(); for ( size_t n = 0; n < nCount; n++ ) { m_aSubgroups[n]->UpdateGroupAndSubgroupsLines(); @@ -1607,11 +1550,11 @@ wxString wxFileConfigGroup::GetFullName() const // use binary search because the array is sorted wxFileConfigEntry * -wxFileConfigGroup::FindEntry(const wxChar *szName) const +wxFileConfigGroup::FindEntry(const wxString& name) const { size_t i, lo = 0, - hi = m_aEntries.Count(); + hi = m_aEntries.GetCount(); int res; wxFileConfigEntry *pEntry; @@ -1620,9 +1563,9 @@ wxFileConfigGroup::FindEntry(const wxChar *szName) const pEntry = m_aEntries[i]; #if wxCONFIG_CASE_SENSITIVE - res = wxStrcmp(pEntry->Name(), szName); + res = pEntry->Name().compare(name); #else - res = wxStricmp(pEntry->Name(), szName); + res = pEntry->Name().CmpNoCase(name); #endif if ( res > 0 ) @@ -1637,11 +1580,11 @@ wxFileConfigGroup::FindEntry(const wxChar *szName) const } wxFileConfigGroup * -wxFileConfigGroup::FindSubgroup(const wxChar *szName) const +wxFileConfigGroup::FindSubgroup(const wxString& name) const { size_t i, lo = 0, - hi = m_aSubgroups.Count(); + hi = m_aSubgroups.GetCount(); int res; wxFileConfigGroup *pGroup; @@ -1650,9 +1593,9 @@ wxFileConfigGroup::FindSubgroup(const wxChar *szName) const pGroup = m_aSubgroups[i]; #if wxCONFIG_CASE_SENSITIVE - res = wxStrcmp(pGroup->Name(), szName); + res = pGroup->Name().compare(name); #else - res = wxStricmp(pGroup->Name(), szName); + res = pGroup->Name().CmpNoCase(name); #endif if ( res > 0 ) @@ -1703,9 +1646,9 @@ wxFileConfigGroup *wxFileConfigGroup::AddSubgroup(const wxString& strName) delete several of them. */ -bool wxFileConfigGroup::DeleteSubgroupByName(const wxChar *szName) +bool wxFileConfigGroup::DeleteSubgroupByName(const wxString& name) { - wxFileConfigGroup * const pGroup = FindSubgroup(szName); + wxFileConfigGroup * const pGroup = FindSubgroup(name); return pGroup ? DeleteSubgroup(pGroup) : false; } @@ -1732,7 +1675,7 @@ bool wxFileConfigGroup::DeleteSubgroup(wxFileConfigGroup *pGroup) : wxEmptyString ); // delete all entries... - size_t nCount = pGroup->m_aEntries.Count(); + size_t nCount = pGroup->m_aEntries.GetCount(); wxLogTrace(FILECONF_TRACE_MASK, _T("Removing %lu entries"), (unsigned long)nCount ); @@ -1751,7 +1694,7 @@ bool wxFileConfigGroup::DeleteSubgroup(wxFileConfigGroup *pGroup) } // ...and subgroups of this subgroup - nCount = pGroup->m_aSubgroups.Count(); + nCount = pGroup->m_aSubgroups.GetCount(); wxLogTrace( FILECONF_TRACE_MASK, _T("Removing %lu subgroups"), (unsigned long)nCount ); @@ -1785,11 +1728,11 @@ bool wxFileConfigGroup::DeleteSubgroup(wxFileConfigGroup *pGroup) // our last entry is being deleted, so find the last one which // stays by going back until we find a subgroup or reach the // group line - const size_t nSubgroups = m_aSubgroups.Count(); + const size_t nSubgroups = m_aSubgroups.GetCount(); m_pLastGroup = NULL; for ( wxFileConfigLineList *pl = pLine->Prev(); - pl && pl != m_pLine && !m_pLastGroup; + pl && !m_pLastGroup; pl = pl->Prev() ) { // does this line belong to our subgroup? @@ -1803,6 +1746,9 @@ bool wxFileConfigGroup::DeleteSubgroup(wxFileConfigGroup *pGroup) break; } } + + if ( pl == m_pLine ) + break; } } @@ -1821,9 +1767,9 @@ bool wxFileConfigGroup::DeleteSubgroup(wxFileConfigGroup *pGroup) return true; } -bool wxFileConfigGroup::DeleteEntry(const wxChar *szName) +bool wxFileConfigGroup::DeleteEntry(const wxString& name) { - wxFileConfigEntry *pEntry = FindEntry(szName); + wxFileConfigEntry *pEntry = FindEntry(name); if ( !pEntry ) { // entry doesn't exist, nothing to do @@ -1840,7 +1786,7 @@ bool wxFileConfigGroup::DeleteEntry(const wxChar *szName) // go back until we find another entry or reach the group's line wxFileConfigEntry *pNewLast = NULL; - size_t n, nEntries = m_aEntries.Count(); + size_t n, nEntries = m_aEntries.GetCount(); wxFileConfigLineList *pl; for ( pl = pLine->Prev(); pl != m_pLine; pl = pl->Prev() ) { // is it our subgroup? @@ -1976,18 +1922,18 @@ void wxFileConfigEntry::SetValue(const wxString& strValue, bool bUser) int CompareEntries(wxFileConfigEntry *p1, wxFileConfigEntry *p2) { #if wxCONFIG_CASE_SENSITIVE - return wxStrcmp(p1->Name(), p2->Name()); + return p1->Name().compare(p2->Name()); #else - return wxStricmp(p1->Name(), p2->Name()); + return p1->Name().CmpNoCase(p2->Name()); #endif } int CompareGroups(wxFileConfigGroup *p1, wxFileConfigGroup *p2) { #if wxCONFIG_CASE_SENSITIVE - return wxStrcmp(p1->Name(), p2->Name()); + return p1->Name().compare(p2->Name()); #else - return wxStricmp(p1->Name(), p2->Name()); + return p1->Name().CmpNoCase(p2->Name()); #endif }