]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/fileconf.cpp
corrected a type in the constructor from two points
[wxWidgets.git] / src / common / fileconf.cpp
index 21cdbf640d4bc42530ea59745e56c8a6cdc44410..cf8ad6879af2862b4cfc8079eacb2d6875254855 100644 (file)
 // global functions declarations
 // ----------------------------------------------------------------------------
 
 // 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
 // compare functions for sorting the arrays
-static int CompareEntries(wxFileConfig::ConfigEntry *p1,
-                          wxFileConfig::ConfigEntry *p2);
-static int CompareGroups(wxFileConfig::ConfigGroup *p1,
-                         wxFileConfig::ConfigGroup *p2);
+static int CompareEntries(ConfigEntry *p1, ConfigEntry *p2);
+static int CompareGroups(ConfigGroup *p1, ConfigGroup *p2);
 
 // filter strings
 
 // 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
 
 // ============================================================================
 // implementation
@@ -97,6 +93,8 @@ wxString wxFileConfig::GetGlobalDir()
     strDir = "/etc/";
   #elif defined(__WXSTUBS__)
     wxASSERT_MSG( FALSE, "TODO" ) ;
     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);
   #else // Windows
     char szWinDir[MAX_PATH];
     ::GetWindowsDirectory(szWinDir, MAX_PATH);
@@ -111,9 +109,15 @@ wxString wxFileConfig::GetGlobalDir()
 wxString wxFileConfig::GetLocalDir()
 {
   wxString strDir;
 wxString wxFileConfig::GetLocalDir()
 {
   wxString strDir;
-  
+
   wxGetHomeDir(&strDir);
 
   wxGetHomeDir(&strDir);
 
+#ifdef  __UNIX__
+  if (strDir.Last() != '/') strDir << '/';
+#else
+  if (strDir.Last() != '\\') strDir << '\\';
+#endif
+
   return strDir;
 }
 
   return strDir;
 }
 
@@ -289,8 +293,8 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
       pEnd = pStart;
 
       while ( *++pEnd != ']' ) {
       pEnd = pStart;
 
       while ( *++pEnd != ']' ) {
-        if ( !IsValid(*pEnd) && *pEnd != ' ' )  // allow spaces in group names
-          break;
+        if ( *pEnd == '\n' || *pEnd == '\0' )
+            break;
       }
 
       if ( *pEnd != ']' ) {
       }
 
       if ( *pEnd != ']' ) {
@@ -302,7 +306,8 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
       // group name here is always considered as abs path
       wxString strGroup;
       pStart++;
       // 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);
 
       // will create it if doesn't yet exist
       SetPath(strGroup);
@@ -334,10 +339,17 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
     }
     else {                        // a key
       const char *pEnd = pStart;
     }
     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++;
         pEnd++;
+      }
 
 
-      wxString strKey(pStart, pEnd);
+      wxString strKey(FilterInEntryName(wxString(pStart, pEnd)));
 
       // skip whitespace
       while ( isspace(*pEnd) )
 
       // skip whitespace
       while ( isspace(*pEnd) )
@@ -384,7 +396,7 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
         while ( isspace(*pEnd) )
           pEnd++;
 
         while ( isspace(*pEnd) )
           pEnd++;
 
-        pEntry->SetValue(FilterIn(pEnd), FALSE /* read from file */);
+        pEntry->SetValue(FilterInValue(pEnd), FALSE /* read from file */);
       }
     }
   }
       }
     }
   }
@@ -581,7 +593,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
   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();
 
     // ... except if it's empty in which case it's a way to force it's creation
     m_pCurrentGroup->SetDirty();
@@ -594,18 +606,12 @@ bool wxFileConfig::Write(const wxString& key, const wxString& szValue)
 
     // check that the name is reasonable
     if ( strName[0u] == wxCONFIG_IMMUTABLE_PREFIX ) {
 
     // 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;
     }
 
                  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 )
 
     ConfigEntry *pEntry = m_pCurrentGroup->FindEntry(strName);
     if ( pEntry == NULL )
@@ -620,9 +626,9 @@ bool wxFileConfig::Write(const wxString& key, const wxString& szValue)
 bool wxFileConfig::Write(const wxString& key, long lValue)
 {
   // ltoa() is not ANSI :-(
 bool wxFileConfig::Write(const wxString& key, long lValue)
 {
   // ltoa() is not ANSI :-(
-  char szBuf[40];   // should be good for sizeof(long) <= 16 (128 bits)
-  sprintf(szBuf, "%ld", lValue);
-  return Write(key, szBuf);
+  wxString buf;
+  buf.Printf("%ld", lValue);
+  return Write(key, buf);
 }
 
 bool wxFileConfig::Flush(bool /* bCurrentOnly */)
 }
 
 bool wxFileConfig::Flush(bool /* bCurrentOnly */)
@@ -648,6 +654,50 @@ bool wxFileConfig::Flush(bool /* bCurrentOnly */)
   return file.Commit();
 }
 
   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
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // delete groups/entries
 // ----------------------------------------------------------------------------
@@ -698,7 +748,7 @@ bool wxFileConfig::DeleteAll()
 // ----------------------------------------------------------------------------
 
 // append a new line to the end of the list
 // ----------------------------------------------------------------------------
 
 // append a new line to the end of the list
-wxFileConfig::LineList *wxFileConfig::LineListAppend(const wxString& str)
+LineList *wxFileConfig::LineListAppend(const wxString& str)
 {
   LineList *pLine = new LineList(str);
 
 {
   LineList *pLine = new LineList(str);
 
@@ -717,7 +767,7 @@ wxFileConfig::LineList *wxFileConfig::LineListAppend(const wxString& str)
 }
 
 // insert a new line after the given one or in the very beginning if !pLine
 }
 
 // insert a new line after the given one or in the very beginning if !pLine
-wxFileConfig::LineList *wxFileConfig::LineListInsert(const wxString& str,
+LineList *wxFileConfig::LineListInsert(const wxString& str,
                                                      LineList *pLine)
 {
   if ( pLine == m_linesTail )
                                                      LineList *pLine)
 {
   if ( pLine == m_linesTail )
@@ -756,7 +806,7 @@ void wxFileConfig::LineListRemove(LineList *pLine)
   // last entry?
   if ( pNext == NULL )
     m_linesTail = pPrev;
   // last entry?
   if ( pNext == NULL )
     m_linesTail = pPrev;
-  else    
+  else
     pNext->SetPrev(pPrev);
 
   delete pLine;
     pNext->SetPrev(pPrev);
 
   delete pLine;
@@ -776,7 +826,7 @@ bool wxFileConfig::LineListIsEmpty()
 // ----------------------------------------------------------------------------
 
 // ctor
 // ----------------------------------------------------------------------------
 
 // ctor
-wxFileConfig::ConfigGroup::ConfigGroup(wxFileConfig::ConfigGroup *pParent,
+ConfigGroup::ConfigGroup(ConfigGroup *pParent,
                                        const wxString& strName,
                                        wxFileConfig *pConfig)
                          : m_aEntries(CompareEntries),
                                        const wxString& strName,
                                        wxFileConfig *pConfig)
                          : m_aEntries(CompareEntries),
@@ -793,7 +843,7 @@ wxFileConfig::ConfigGroup::ConfigGroup(wxFileConfig::ConfigGroup *pParent,
 }
 
 // dtor deletes all children
 }
 
 // dtor deletes all children
-wxFileConfig::ConfigGroup::~ConfigGroup()
+ConfigGroup::~ConfigGroup()
 {
   // entries
   size_t n, nCount = m_aEntries.Count();
 {
   // entries
   size_t n, nCount = m_aEntries.Count();
@@ -810,7 +860,7 @@ wxFileConfig::ConfigGroup::~ConfigGroup()
 // line
 // ----------------------------------------------------------------------------
 
 // line
 // ----------------------------------------------------------------------------
 
-void wxFileConfig::ConfigGroup::SetLine(LineList *pLine)
+void ConfigGroup::SetLine(LineList *pLine)
 {
   wxASSERT( m_pLine == NULL ); // shouldn't be called twice
 
 {
   wxASSERT( m_pLine == NULL ); // shouldn't be called twice
 
@@ -846,12 +896,12 @@ void wxFileConfig::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.
       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
 // have it or in the very beginning if we're the root group.
 
 // 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
 // have it or in the very beginning if we're the root group.
-wxFileConfig::LineList *wxFileConfig::ConfigGroup::GetGroupLine()
+LineList *ConfigGroup::GetGroupLine()
 {
   if ( m_pLine == NULL ) {
     ConfigGroup *pParent = Parent();
 {
   if ( m_pLine == NULL ) {
     ConfigGroup *pParent = Parent();
@@ -859,7 +909,7 @@ wxFileConfig::LineList *wxFileConfig::ConfigGroup::GetGroupLine()
     // this group wasn't present in local config file, add it now
     if ( pParent != NULL ) {
       wxString strFullName;
     // this group wasn't present in local config file, add it now
     if ( pParent != NULL ) {
       wxString strFullName;
-      strFullName << "[" << GetFullName().c_str() + 1 << "]"; // +1: no '/'
+      strFullName << "[" << (GetFullName().c_str() + 1) << "]"; // +1: no '/'
       m_pLine = m_pConfig->LineListInsert(strFullName,
                                           pParent->GetLastGroupLine());
       pParent->SetLastGroup(this);  // we're surely after all the others
       m_pLine = m_pConfig->LineListInsert(strFullName,
                                           pParent->GetLastGroupLine());
       pParent->SetLastGroup(this);  // we're surely after all the others
@@ -876,12 +926,12 @@ wxFileConfig::LineList *wxFileConfig::ConfigGroup::GetGroupLine()
 // Return the last line belonging to the subgroups of this group (after which
 // we can add a new subgroup), if we don't have any subgroups or entries our
 // last line is the group line (m_pLine) itself.
 // Return the last line belonging to the subgroups of this group (after which
 // we can add a new subgroup), if we don't have any subgroups or entries our
 // last line is the group line (m_pLine) itself.
-wxFileConfig::LineList *wxFileConfig::ConfigGroup::GetLastGroupLine()
+LineList *ConfigGroup::GetLastGroupLine()
 {
   // if we have any subgroups, our last line is the last line of the last
   // subgroup
   if ( m_pLastGroup != NULL ) {
 {
   // if we have any subgroups, our last line is the last line of the last
   // subgroup
   if ( m_pLastGroup != NULL ) {
-    wxFileConfig::LineList *pLine = m_pLastGroup->GetLastGroupLine();
+    LineList *pLine = m_pLastGroup->GetLastGroupLine();
 
     wxASSERT( pLine != NULL );  // last group must have !NULL associated line
     return pLine;
 
     wxASSERT( pLine != NULL );  // last group must have !NULL associated line
     return pLine;
@@ -894,10 +944,10 @@ wxFileConfig::LineList *wxFileConfig::ConfigGroup::GetLastGroupLine()
 // return the last line belonging to the entries of this group (after which
 // we can add a new entry), if we don't have any entries we will add the new
 // one immediately after the group line itself.
 // return the last line belonging to the entries of this group (after which
 // we can add a new entry), if we don't have any entries we will add the new
 // one immediately after the group line itself.
-wxFileConfig::LineList *wxFileConfig::ConfigGroup::GetLastEntryLine()
+LineList *ConfigGroup::GetLastEntryLine()
 {
   if ( m_pLastEntry != NULL ) {
 {
   if ( m_pLastEntry != NULL ) {
-    wxFileConfig::LineList *pLine = m_pLastEntry->GetLine();
+    LineList *pLine = m_pLastEntry->GetLine();
 
     wxASSERT( pLine != NULL );  // last entry must have !NULL associated line
     return pLine;
 
     wxASSERT( pLine != NULL );  // last entry must have !NULL associated line
     return pLine;
@@ -911,7 +961,19 @@ wxFileConfig::LineList *wxFileConfig::ConfigGroup::GetLastEntryLine()
 // group name
 // ----------------------------------------------------------------------------
 
 // group name
 // ----------------------------------------------------------------------------
 
-wxString wxFileConfig::ConfigGroup::GetFullName() const
+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() )
     return Parent()->GetFullName() + wxCONFIG_PATH_SEPARATOR + Name();
 {
   if ( Parent() )
     return Parent()->GetFullName() + wxCONFIG_PATH_SEPARATOR + Name();
@@ -924,14 +986,14 @@ wxString wxFileConfig::ConfigGroup::GetFullName() const
 // ----------------------------------------------------------------------------
 
 // use binary search because the array is sorted
 // ----------------------------------------------------------------------------
 
 // use binary search because the array is sorted
-wxFileConfig::ConfigEntry *
-wxFileConfig::ConfigGroup::FindEntry(const char *szName) const
+ConfigEntry *
+ConfigGroup::FindEntry(const char *szName) const
 {
   size_t i,
        lo = 0,
        hi = m_aEntries.Count();
   int res;
 {
   size_t i,
        lo = 0,
        hi = m_aEntries.Count();
   int res;
-  wxFileConfig::ConfigEntry *pEntry;
+  ConfigEntry *pEntry;
 
   while ( lo < hi ) {
     i = (lo + hi)/2;
 
   while ( lo < hi ) {
     i = (lo + hi)/2;
@@ -954,14 +1016,14 @@ wxFileConfig::ConfigGroup::FindEntry(const char *szName) const
   return NULL;
 }
 
   return NULL;
 }
 
-wxFileConfig::ConfigGroup *
-wxFileConfig::ConfigGroup::FindSubgroup(const char *szName) const
+ConfigGroup *
+ConfigGroup::FindSubgroup(const char *szName) const
 {
   size_t i,
        lo = 0,
        hi = m_aSubgroups.Count();
   int res;
 {
   size_t i,
        lo = 0,
        hi = m_aSubgroups.Count();
   int res;
-  wxFileConfig::ConfigGroup *pGroup;
+  ConfigGroup *pGroup;
 
   while ( lo < hi ) {
     i = (lo + hi)/2;
 
   while ( lo < hi ) {
     i = (lo + hi)/2;
@@ -989,8 +1051,8 @@ wxFileConfig::ConfigGroup::FindSubgroup(const char *szName) const
 // ----------------------------------------------------------------------------
 
 // create a new entry and add it to the current group
 // ----------------------------------------------------------------------------
 
 // create a new entry and add it to the current group
-wxFileConfig::ConfigEntry *
-wxFileConfig::ConfigGroup::AddEntry(const wxString& strName, int nLine)
+ConfigEntry *
+ConfigGroup::AddEntry(const wxString& strName, int nLine)
 {
   wxASSERT( FindEntry(strName) == NULL );
 
 {
   wxASSERT( FindEntry(strName) == NULL );
 
@@ -1001,8 +1063,8 @@ wxFileConfig::ConfigGroup::AddEntry(const wxString& strName, int nLine)
 }
 
 // create a new group and add it to the current group
 }
 
 // create a new group and add it to the current group
-wxFileConfig::ConfigGroup *
-wxFileConfig::ConfigGroup::AddSubgroup(const wxString& strName)
+ConfigGroup *
+ConfigGroup::AddSubgroup(const wxString& strName)
 {
   wxASSERT( FindSubgroup(strName) == NULL );
 
 {
   wxASSERT( FindSubgroup(strName) == NULL );
 
@@ -1023,7 +1085,7 @@ wxFileConfig::ConfigGroup::AddSubgroup(const wxString& strName)
   delete several of them.
  */
 
   delete several of them.
  */
 
-bool wxFileConfig::ConfigGroup::DeleteSubgroupByName(const char *szName)
+bool ConfigGroup::DeleteSubgroupByName(const char *szName)
 {
   return DeleteSubgroup(FindSubgroup(szName));
 }
 {
   return DeleteSubgroup(FindSubgroup(szName));
 }
@@ -1031,7 +1093,7 @@ bool wxFileConfig::ConfigGroup::DeleteSubgroupByName(const char *szName)
 // doesn't delete the subgroup itself, but does remove references to it from
 // all other data structures (and normally the returned pointer should be
 // deleted a.s.a.p. because there is nothing much to be done with it anyhow)
 // doesn't delete the subgroup itself, but does remove references to it from
 // all other data structures (and normally the returned pointer should be
 // deleted a.s.a.p. because there is nothing much to be done with it anyhow)
-bool wxFileConfig::ConfigGroup::DeleteSubgroup(ConfigGroup *pGroup)
+bool ConfigGroup::DeleteSubgroup(ConfigGroup *pGroup)
 {
   wxCHECK( pGroup != NULL, FALSE ); // deleting non existing group?
 
 {
   wxCHECK( pGroup != NULL, FALSE ); // deleting non existing group?
 
@@ -1095,7 +1157,7 @@ bool wxFileConfig::ConfigGroup::DeleteSubgroup(ConfigGroup *pGroup)
   return TRUE;
 }
 
   return TRUE;
 }
 
-bool wxFileConfig::ConfigGroup::DeleteEntry(const char *szName)
+bool ConfigGroup::DeleteEntry(const char *szName)
 {
   ConfigEntry *pEntry = FindEntry(szName);
   wxCHECK( pEntry != NULL, FALSE );  // deleting non existing item?
 {
   ConfigEntry *pEntry = FindEntry(szName);
   wxCHECK( pEntry != NULL, FALSE );  // deleting non existing item?
@@ -1148,7 +1210,7 @@ bool wxFileConfig::ConfigGroup::DeleteEntry(const char *szName)
 // ----------------------------------------------------------------------------
 //
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 //
 // ----------------------------------------------------------------------------
-void wxFileConfig::ConfigGroup::SetDirty()
+void ConfigGroup::SetDirty()
 {
   m_bDirty = TRUE;
   if ( Parent() != NULL )             // propagate upwards
 {
   m_bDirty = TRUE;
   if ( Parent() != NULL )             // propagate upwards
@@ -1162,7 +1224,7 @@ void wxFileConfig::ConfigGroup::SetDirty()
 // ----------------------------------------------------------------------------
 // ctor
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // ctor
 // ----------------------------------------------------------------------------
-wxFileConfig::ConfigEntry::ConfigEntry(wxFileConfig::ConfigGroup *pParent,
+ConfigEntry::ConfigEntry(ConfigGroup *pParent,
                                        const wxString& strName,
                                        int nLine)
                          : m_strName(strName)
                                        const wxString& strName,
                                        int nLine)
                          : m_strName(strName)
@@ -1184,7 +1246,7 @@ wxFileConfig::ConfigEntry::ConfigEntry(wxFileConfig::ConfigGroup *pParent,
 // set value
 // ----------------------------------------------------------------------------
 
 // set value
 // ----------------------------------------------------------------------------
 
-void wxFileConfig::ConfigEntry::SetLine(LineList *pLine)
+void ConfigEntry::SetLine(LineList *pLine)
 {
   if ( m_pLine != NULL ) {
     wxLogWarning(_("entry '%s' appears more than once in group '%s'"),
 {
   if ( m_pLine != NULL ) {
     wxLogWarning(_("entry '%s' appears more than once in group '%s'"),
@@ -1197,7 +1259,7 @@ void wxFileConfig::ConfigEntry::SetLine(LineList *pLine)
 
 // second parameter is FALSE if we read the value from file and prevents the
 // entry from being marked as 'dirty'
 
 // second parameter is FALSE if we read the value from file and prevents the
 // entry from being marked as 'dirty'
-void wxFileConfig::ConfigEntry::SetValue(const wxString& strValue, bool bUser)
+void ConfigEntry::SetValue(const wxString& strValue, bool bUser)
 {
   if ( bUser && IsImmutable() ) {
     wxLogWarning(_("attempt to change immutable key '%s' ignored."),
 {
   if ( bUser && IsImmutable() ) {
     wxLogWarning(_("attempt to change immutable key '%s' ignored."),
@@ -1212,7 +1274,7 @@ void wxFileConfig::ConfigEntry::SetValue(const wxString& strValue, bool bUser)
   m_strValue = strValue;
 
   if ( bUser ) {
   m_strValue = strValue;
 
   if ( bUser ) {
-    wxString strVal = FilterOut(strValue);
+    wxString strVal = FilterOutValue(strValue);
     wxString strLine;
     strLine << m_strName << " = " << strVal;
 
     wxString strLine;
     strLine << m_strName << " = " << strVal;
 
@@ -1222,7 +1284,7 @@ void wxFileConfig::ConfigEntry::SetValue(const wxString& strValue, bool bUser)
     }
     else {
       // add a new line to the file
     }
     else {
       // add a new line to the file
-      wxASSERT( m_nLine == NOT_FOUND );   // consistency check
+      wxASSERT( m_nLine == wxNOT_FOUND );   // consistency check
 
       m_pLine = Group()->Config()->LineListInsert(strLine,
                                                   Group()->GetLastEntryLine());
 
       m_pLine = Group()->Config()->LineListInsert(strLine,
                                                   Group()->GetLastEntryLine());
@@ -1233,7 +1295,7 @@ void wxFileConfig::ConfigEntry::SetValue(const wxString& strValue, bool bUser)
   }
 }
 
   }
 }
 
-void wxFileConfig::ConfigEntry::SetDirty()
+void ConfigEntry::SetDirty()
 {
   m_bDirty = TRUE;
   Group()->SetDirty();
 {
   m_bDirty = TRUE;
   Group()->SetDirty();
@@ -1247,8 +1309,8 @@ void wxFileConfig::ConfigEntry::SetDirty()
 // compare functions for array sorting
 // ----------------------------------------------------------------------------
 
 // compare functions for array sorting
 // ----------------------------------------------------------------------------
 
-int CompareEntries(wxFileConfig::ConfigEntry *p1,
-                   wxFileConfig::ConfigEntry *p2)
+int CompareEntries(ConfigEntry *p1,
+                   ConfigEntry *p2)
 {
   #if wxCONFIG_CASE_SENSITIVE
     return strcmp(p1->Name(), p2->Name());
 {
   #if wxCONFIG_CASE_SENSITIVE
     return strcmp(p1->Name(), p2->Name());
@@ -1257,8 +1319,8 @@ int CompareEntries(wxFileConfig::ConfigEntry *p1,
   #endif
 }
 
   #endif
 }
 
-int CompareGroups(wxFileConfig::ConfigGroup *p1,
-                  wxFileConfig::ConfigGroup *p2)
+int CompareGroups(ConfigGroup *p1,
+                  ConfigGroup *p2)
 {
   #if wxCONFIG_CASE_SENSITIVE
     return strcmp(p1->Name(), p2->Name());
 {
   #if wxCONFIG_CASE_SENSITIVE
     return strcmp(p1->Name(), p2->Name());
@@ -1271,8 +1333,8 @@ int CompareGroups(wxFileConfig::ConfigGroup *p1,
 // filter functions
 // ----------------------------------------------------------------------------
 
 // filter functions
 // ----------------------------------------------------------------------------
 
-// undo FilterOut
-wxString FilterIn(const wxString& str)
+// undo FilterOutValue
+static wxString FilterInValue(const wxString& str)
 {
   wxString strResult;
   strResult.Alloc(str.Len());
 {
   wxString strResult;
   strResult.Alloc(str.Len());
@@ -1318,11 +1380,11 @@ wxString FilterIn(const wxString& str)
 }
 
 // quote the string before writing it to file
 }
 
 // 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;
       return str;
-   
+
   wxString strResult;
   strResult.Alloc(str.Len());
 
   wxString strResult;
   strResult.Alloc(str.Len());
 
@@ -1372,3 +1434,42 @@ wxString FilterOut(const wxString& str)
 
   return strResult;
 }
 
   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;
+}
+