X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/503602dfe7fd468159d8d563657ad10c0bf6601f..7b504551c292ecb4296693983161ac5ad03745f6:/src/common/fileconf.cpp diff --git a/src/common/fileconf.cpp b/src/common/fileconf.cpp index daaa9291fb..022a830255 100644 --- a/src/common/fileconf.cpp +++ b/src/common/fileconf.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: fileconf.cpp +// Name: src/common/fileconf.cpp // Purpose: implementation of wxFileConfig derivation of wxConfig // Author: Vadim Zeitlin // Modified by: @@ -10,10 +10,6 @@ // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) -#pragma implementation "fileconf.h" -#endif - // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- @@ -275,7 +271,7 @@ wxString wxFileConfig::GetGlobalDir() strDir = wxMacFindFolder( (short) kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder ) ; #elif defined( __UNIX__ ) strDir = wxT("/etc/"); -#elif defined(__WXPM__) +#elif defined(__OS2__) ULONG aulSysInfo[QSV_MAX] = {0}; UINT drive; APIRET rc; @@ -294,7 +290,7 @@ wxString wxFileConfig::GetGlobalDir() return wxT(".\\"); #elif defined(__WXWINCE__) strDir = wxT("\\Windows\\"); -#elif // Windows +#else // Windows wxChar szWinDir[MAX_PATH]; ::GetWindowsDirectory(szWinDir, MAX_PATH); @@ -454,16 +450,16 @@ wxFileConfig::wxFileConfig(const wxString& appName, const wxString& vendorName, { if ( !m_strLocalFile.empty() && !wxIsAbsolutePath(m_strLocalFile) ) { - wxString strLocal = m_strLocalFile; + const wxString strLocalOrig = m_strLocalFile; m_strLocalFile = GetLocalDir(); - m_strLocalFile << strLocal; + m_strLocalFile << strLocalOrig; } if ( !m_strGlobalFile.empty() && !wxIsAbsolutePath(m_strGlobalFile) ) { - wxString strGlobal = m_strGlobalFile; + const wxString strGlobalOrig = m_strGlobalFile; m_strGlobalFile = GetGlobalDir(); - m_strGlobalFile << strGlobal; + m_strGlobalFile << strGlobalOrig; } } @@ -495,7 +491,7 @@ wxFileConfig::wxFileConfig(wxInputStream &inStream, wxMBConv& conv) char buf[1024]; do { - inStream.Read(buf, WXSIZEOF(buf)); + inStream.Read(buf, WXSIZEOF(buf)-1); // leave room for the NULL const wxStreamError err = inStream.GetLastError(); @@ -505,7 +501,12 @@ wxFileConfig::wxFileConfig(wxInputStream &inStream, wxMBConv& conv) break; } - strTmp.append(wxConvertMB2WX(buf), inStream.LastRead()); + // FIXME: this is broken because if we have part of multibyte + // character in the buffer (and another part hasn't been + // read yet) we're going to lose data because of conversion + // errors + buf[inStream.LastRead()] = '\0'; + strTmp += conv.cMB2WX(buf); } while ( !inStream.Eof() ); @@ -543,6 +544,7 @@ wxFileConfig::wxFileConfig(wxInputStream &inStream, wxMBConv& conv) Parse(memText, true /* local */); SetRootPath(); + ResetDirty(); } #endif // wxUSE_STREAMS @@ -570,7 +572,7 @@ wxFileConfig::~wxFileConfig() // parse a config file // ---------------------------------------------------------------------------- -void wxFileConfig::Parse(wxTextBuffer& buffer, bool bLocal) +void wxFileConfig::Parse(const wxTextBuffer& buffer, bool bLocal) { const wxChar *pStart; const wxChar *pEnd; @@ -587,7 +589,7 @@ void wxFileConfig::Parse(wxTextBuffer& buffer, bool bLocal) { LineListAppend(strLine); - // let the root group have it start line as well + // let the root group have its start line as well if ( !n ) { m_pCurrentGroup->SetLine(m_linesTail); @@ -662,7 +664,7 @@ void wxFileConfig::Parse(wxTextBuffer& buffer, bool bLocal) } } else { // a key - const wxChar *pEnd = pStart; + pEnd = pStart; while ( *pEnd && *pEnd != wxT('=') /* && !wxIsspace(*pEnd)*/ ) { if ( *pEnd == wxT('\\') ) { // next character may be space or not - still take it because it's @@ -740,13 +742,14 @@ void wxFileConfig::SetRootPath() m_pCurrentGroup = m_pRootGroup; } -void wxFileConfig::SetPath(const wxString& strPath) +bool +wxFileConfig::DoSetPath(const wxString& strPath, bool createMissingComponents) { wxArrayString aParts; if ( strPath.empty() ) { SetRootPath(); - return; + return true; } if ( strPath[0] == wxCONFIG_PATH_SEPARATOR ) { @@ -766,7 +769,13 @@ void wxFileConfig::SetPath(const wxString& strPath) for ( n = 0; n < aParts.Count(); n++ ) { wxFileConfigGroup *pNextGroup = m_pCurrentGroup->FindSubgroup(aParts[n]); if ( pNextGroup == NULL ) + { + if ( !createMissingComponents ) + return false; + pNextGroup = m_pCurrentGroup->AddSubgroup(aParts[n]); + } + m_pCurrentGroup = pNextGroup; } @@ -775,6 +784,13 @@ void wxFileConfig::SetPath(const wxString& strPath) for ( n = 0; n < aParts.Count(); n++ ) { m_strPath << wxCONFIG_PATH_SEPARATOR << aParts[n]; } + + return true; +} + +void wxFileConfig::SetPath(const wxString& strPath) +{ + DoSetPath(strPath, true /* create missing path components */); } // ---------------------------------------------------------------------------- @@ -851,10 +867,20 @@ size_t wxFileConfig::GetNumberOfGroups(bool bRecursive) const bool wxFileConfig::HasGroup(const wxString& strName) const { - wxConfigPathChanger path(this, strName); + // special case: DoSetPath("") does work as it's equivalent to DoSetPath("/") + // but there is no group with empty name so treat this separately + if ( strName.empty() ) + return false; - wxFileConfigGroup *pGroup = m_pCurrentGroup->FindSubgroup(path.Name()); - return pGroup != NULL; + const wxString pathOld = GetPath(); + + wxFileConfig *self = wx_const_cast(wxFileConfig *, this); + const bool + rc = self->DoSetPath(strName, false /* don't create missing components */); + + self->SetPath(pathOld); + + return rc; } bool wxFileConfig::HasEntry(const wxString& strName) const @@ -1013,7 +1039,9 @@ bool wxFileConfig::Save(wxOutputStream& os, wxMBConv& conv) { wxString line = p->Text(); line += wxTextFile::GetEOL(); - if ( !os.Write(line.mb_str(conv), line.length()) ) + + wxCharBuffer buf(line.mb_str(conv)); + if ( !os.Write(buf, strlen(buf)) ) { wxLogError(_("Error saving user configuration data.")); @@ -1090,12 +1118,13 @@ bool wxFileConfig::DeleteEntry(const wxString& key, bool bGroupIfEmptyAlso) if ( !m_pCurrentGroup->DeleteEntry(path.Name()) ) return false; + SetDirty(); + if ( bGroupIfEmptyAlso && m_pCurrentGroup->IsEmpty() ) { if ( m_pCurrentGroup != m_pRootGroup ) { wxFileConfigGroup *pGroup = m_pCurrentGroup; SetPath(wxT("..")); // changes m_pCurrentGroup! - if ( m_pCurrentGroup->DeleteSubgroupByName(pGroup->Name()) ) - SetDirty(); + m_pCurrentGroup->DeleteSubgroupByName(pGroup->Name()); } //else: never delete the root group } @@ -1256,6 +1285,9 @@ void wxFileConfig::LineListRemove(wxFileConfigLineList *pLine) else pNext->SetPrev(pPrev); + if ( m_pRootGroup->GetGroupLine() == pLine ) + m_pRootGroup->SetLine(m_linesHead); + wxLogTrace( FILECONF_TRACE_MASK, _T(" head: %s"), ((m_linesHead) ? m_linesHead->Text().c_str() : wxEmptyString) ); @@ -1315,7 +1347,11 @@ wxFileConfigGroup::~wxFileConfigGroup() void wxFileConfigGroup::SetLine(wxFileConfigLineList *pLine) { - wxASSERT( m_pLine == 0 ); // shouldn't be called twice + // for a normal (i.e. not root) group this method shouldn't be called twice + // unless we are resetting the line + wxASSERT_MSG( !m_pParent || !m_pLine || !pLine, + _T("changing line for a non-root group?") ); + m_pLine = pLine; } @@ -1839,20 +1875,11 @@ void wxFileConfigEntry::SetValue(const wxString& strValue, bool bUser) } else // this entry didn't exist in the local file { - // add a new line to the file: note the hack for the root group - // which is special in that it doesn't have its own group line - // (something like "[/]") and so the line we get for it may be not - // its line at all if it doesn't have any entries - // - // this is definitely not the right place to fix it but changing - // the root group to have NULL m_pLine will probably break too - // much stuff elsewhere so I don't dare to do it... + // add a new line to the file: note that line returned by + // GetLastEntryLine() may be NULL if we're in the root group and it + // doesn't have any entries yet, but this is ok as passing NULL + // line to LineListInsert() means to prepend new line to the list wxFileConfigLineList *line = Group()->GetLastEntryLine(); - if ( !Group()->Parent() && line == Group()->GetGroupLine() ) - { - // prepend the first root group entry to the head of the list - line = NULL; - } m_pLine = Group()->Config()->LineListInsert(strLine, line); Group()->SetLastEntry(this); @@ -2049,4 +2076,3 @@ static wxString GetAppName(const wxString& appName) } #endif // wxUSE_CONFIG -