X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a3ef5bf5045991260005634272633717c0a26174..6c41a418df66b66711eba536526a3085f690782e:/src/common/fileconf.cpp diff --git a/src/common/fileconf.cpp b/src/common/fileconf.cpp index c887bc6b86..cc1567b4ee 100644 --- a/src/common/fileconf.cpp +++ b/src/common/fileconf.cpp @@ -67,20 +67,16 @@ // global functions declarations // ---------------------------------------------------------------------------- -// is 'c' a valid character in group name? -// NB: wxCONFIG_IMMUTABLE_PREFIX and wxCONFIG_PATH_SEPARATOR must be valid chars, -// but _not_ ']' (group name delimiter) -inline bool IsValid(char c) { return isalnum(c) || strchr("@_/-!.*%", c); } - // compare functions for sorting the arrays -static int CompareEntries(ConfigEntry *p1, - ConfigEntry *p2); -static int CompareGroups(ConfigGroup *p1, - ConfigGroup *p2); +static int CompareEntries(ConfigEntry *p1, ConfigEntry *p2); +static int CompareGroups(ConfigGroup *p1, ConfigGroup *p2); // filter strings -static wxString FilterIn(const wxString& str); -static wxString FilterOut(const wxString& str); +static wxString FilterInValue(const wxString& str); +static wxString FilterOutValue(const wxString& str); + +static wxString FilterInEntryName(const wxString& str); +static wxString FilterOutEntryName(const wxString& str); // ============================================================================ // implementation @@ -97,6 +93,8 @@ wxString wxFileConfig::GetGlobalDir() strDir = "/etc/"; #elif defined(__WXSTUBS__) wxASSERT_MSG( FALSE, "TODO" ) ; + #elif defined(__WXMAC__) + wxASSERT_MSG( FALSE, "TODO" ) ; #else // Windows char szWinDir[MAX_PATH]; ::GetWindowsDirectory(szWinDir, MAX_PATH); @@ -200,15 +198,11 @@ void wxFileConfig::Init() wxFileConfig::wxFileConfig(const wxString& appName, const wxString& vendorName, const wxString& strLocal, const wxString& strGlobal, long style) - : wxConfigBase(appName, vendorName, strLocal, strGlobal, style), + : wxConfigBase(!appName && wxTheApp ? wxTheApp->GetAppName() + : appName, + vendorName, strLocal, strGlobal, style), m_strLocalFile(strLocal), m_strGlobalFile(strGlobal) { - // Make up an application name if not supplied - if (appName.IsEmpty() && wxTheApp) - { - SetAppName(wxTheApp->GetAppName()); - } - // Make up names for files if empty if ( m_strLocalFile.IsEmpty() && (style & wxCONFIG_USE_LOCAL_FILE) ) { @@ -295,8 +289,8 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal) pEnd = pStart; while ( *++pEnd != ']' ) { - if ( !IsValid(*pEnd) && *pEnd != ' ' ) // allow spaces in group names - break; + if ( *pEnd == '\n' || *pEnd == '\0' ) + break; } if ( *pEnd != ']' ) { @@ -308,7 +302,8 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal) // group name here is always considered as abs path wxString strGroup; pStart++; - strGroup << wxCONFIG_PATH_SEPARATOR << wxString(pStart, pEnd - pStart); + strGroup << wxCONFIG_PATH_SEPARATOR + << FilterInEntryName(wxString(pStart, pEnd - pStart)); // will create it if doesn't yet exist SetPath(strGroup); @@ -340,10 +335,17 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal) } else { // a key const char *pEnd = pStart; - while ( IsValid(*pEnd) ) + while ( !isspace(*pEnd) ) { + if ( *pEnd == '\\' ) { + // next character may be space or not - still take it because it's + // quoted + pEnd++; + } + pEnd++; + } - wxString strKey(pStart, pEnd); + wxString strKey(FilterInEntryName(wxString(pStart, pEnd))); // skip whitespace while ( isspace(*pEnd) ) @@ -390,7 +392,7 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal) while ( isspace(*pEnd) ) pEnd++; - pEntry->SetValue(FilterIn(pEnd), FALSE /* read from file */); + pEntry->SetValue(FilterInValue(pEnd), FALSE /* read from file */); } } } @@ -587,7 +589,7 @@ bool wxFileConfig::Write(const wxString& key, const wxString& szValue) wxString strName = path.Name(); if ( strName.IsEmpty() ) { // setting the value of a group is an error - wxASSERT_MSG( IsEmpty(szValue), _("can't set value of a group!") ); + wxASSERT_MSG( IsEmpty(szValue), "can't set value of a group!" ); // ... except if it's empty in which case it's a way to force it's creation m_pCurrentGroup->SetDirty(); @@ -600,18 +602,12 @@ bool wxFileConfig::Write(const wxString& key, const wxString& szValue) // check that the name is reasonable if ( strName[0u] == wxCONFIG_IMMUTABLE_PREFIX ) { - wxLogError(_("Entry name can't start with '%c'."), + wxLogError(_("Config entry name cannot start with '%c'."), wxCONFIG_IMMUTABLE_PREFIX); return FALSE; } - for ( const char *pc = strName; *pc != '\0'; pc++ ) { - if ( !IsValid(*pc) ) { - wxLogError(_("Character '%c' is invalid in a config entry name."), - *pc); - return FALSE; - } - } + strName = FilterOutEntryName(strName); ConfigEntry *pEntry = m_pCurrentGroup->FindEntry(strName); if ( pEntry == NULL ) @@ -654,6 +650,50 @@ bool wxFileConfig::Flush(bool /* bCurrentOnly */) return file.Commit(); } +// ---------------------------------------------------------------------------- +// renaming groups/entries +// ---------------------------------------------------------------------------- + +bool wxFileConfig::RenameEntry(const wxString& oldName, + const wxString& newName) +{ + // check that the entry exists + ConfigEntry *oldEntry = m_pCurrentGroup->FindEntry(oldName); + if ( !oldEntry ) + return FALSE; + + // check that the new entry doesn't already exist + if ( m_pCurrentGroup->FindEntry(newName) ) + return FALSE; + + // delete the old entry, create the new one + wxString value = oldEntry->Value(); + if ( !m_pCurrentGroup->DeleteEntry(oldName) ) + return FALSE; + + ConfigEntry *newEntry = m_pCurrentGroup->AddEntry(newName); + newEntry->SetValue(value); + + return TRUE; +} + +bool wxFileConfig::RenameGroup(const wxString& oldName, + const wxString& newName) +{ + // check that the group exists + ConfigGroup *group = m_pCurrentGroup->FindSubgroup(oldName); + if ( !group ) + return FALSE; + + // check that the new group doesn't already exist + if ( m_pCurrentGroup->FindSubgroup(newName) ) + return FALSE; + + group->Rename(newName); + + return TRUE; +} + // ---------------------------------------------------------------------------- // delete groups/entries // ---------------------------------------------------------------------------- @@ -852,7 +892,7 @@ void ConfigGroup::SetLine(LineList *pLine) backwards in the config file (OTOH, it's not that important) and as we would still need to do it for the subgroups the code wouldn't have been significantly less complicated. - */ +*/ // Return the line which contains "[our name]". If we're still not in the list, // add our line to it immediately after the last line of our parent group if we @@ -917,6 +957,18 @@ LineList *ConfigGroup::GetLastEntryLine() // group name // ---------------------------------------------------------------------------- +void ConfigGroup::Rename(const wxString& newName) +{ + m_strName = newName; + + LineList *line = GetGroupLine(); + wxString strFullName; + strFullName << "[" << (GetFullName().c_str() + 1) << "]"; // +1: no '/' + line->SetText(strFullName); + + SetDirty(); +} + wxString ConfigGroup::GetFullName() const { if ( Parent() ) @@ -1052,7 +1104,7 @@ bool ConfigGroup::DeleteSubgroup(ConfigGroup *pGroup) // and subgroups of this sungroup nCount = pGroup->m_aSubgroups.Count(); for ( size_t nGroup = 0; nGroup < nCount; nGroup++ ) { - pGroup->DeleteSubgroup(pGroup->m_aSubgroups[nGroup]); + pGroup->DeleteSubgroup(pGroup->m_aSubgroups[0]); } LineList *pLine = pGroup->m_pLine; @@ -1218,7 +1270,7 @@ void ConfigEntry::SetValue(const wxString& strValue, bool bUser) m_strValue = strValue; if ( bUser ) { - wxString strVal = FilterOut(strValue); + wxString strVal = FilterOutValue(strValue); wxString strLine; strLine << m_strName << " = " << strVal; @@ -1277,8 +1329,8 @@ int CompareGroups(ConfigGroup *p1, // filter functions // ---------------------------------------------------------------------------- -// undo FilterOut -wxString FilterIn(const wxString& str) +// undo FilterOutValue +static wxString FilterInValue(const wxString& str) { wxString strResult; strResult.Alloc(str.Len()); @@ -1324,9 +1376,9 @@ wxString FilterIn(const wxString& str) } // quote the string before writing it to file -wxString FilterOut(const wxString& str) +static wxString FilterOutValue(const wxString& str) { - if(str.IsEmpty()) + if ( !str ) return str; wxString strResult; @@ -1379,9 +1431,41 @@ wxString FilterOut(const wxString& str) return strResult; } +// undo FilterOutEntryName +static wxString FilterInEntryName(const wxString& str) +{ + wxString strResult; + strResult.Alloc(str.Len()); + for ( const char *pc = str.c_str(); *pc != '\0'; pc++ ) { + if ( *pc == '\\' ) + pc++; + strResult += *pc; + } + return strResult; +} +// sanitize entry or group name: insert '\\' before any special characters +static wxString FilterOutEntryName(const wxString& str) +{ + wxString strResult; + strResult.Alloc(str.Len()); + + for ( const char *pc = str.c_str(); *pc != '\0'; pc++ ) { + char c = *pc; + // we explicitly allow some of "safe" chars and 8bit ASCII characters + // which will probably never have special meaning + // NB: note that wxCONFIG_IMMUTABLE_PREFIX and wxCONFIG_PATH_SEPARATOR + // should *not* be quoted + if ( !isalnum(c) && !strchr("@_/-!.*%", c) && ((c & 0x80) == 0) ) + strResult += '\\'; + + strResult += c; + } + + return strResult; +}