]> git.saurik.com Git - wxWidgets.git/commitdiff
added HasEntry/Group function to wxConfig, corrected entry/group deletion
authorVadim Zeitlin <vadim@wxwidgets.org>
Tue, 7 Jul 1998 13:53:19 +0000 (13:53 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Tue, 7 Jul 1998 13:53:19 +0000 (13:53 +0000)
bug (were not deleted from file) in wxFileConfig

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@183 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/config.h
include/wx/fileconf.h
src/common/fileconf.cpp

index d4071bd6ef73b735e3c9e98d886bf950c9f668fb..d1e27b25170f7bed0b4c12dbb613d04e7defa531 100644 (file)
@@ -109,6 +109,15 @@ public:
   virtual bool GetFirstEntry(wxString& str, long& lIndex) = 0;
   virtual bool GetNextEntry (wxString& str, long& lIndex) = 0;
 
+  // tests of existence
+    // returns TRUE if the group by this name exists
+  virtual bool HasGroup(const wxString& strName) const = 0;
+    // same as above, but for an entry
+  virtual bool HasEntry(const wxString& strName) const = 0;
+    // returns TRUE if either a group or an entry with a given name exist
+  bool Exists(const wxString& strName) const
+    { return HasGroup(strName) || HasEntry(strName); }
+
   // key access: returns TRUE if value was really read, FALSE if default used
   // (and if the key is not found the default value is returned.)
     // read a string from the key
@@ -119,7 +128,7 @@ public:
   virtual const char *Read(const char *szKey,
                            const char *szDefault = NULL) const;
     // the same for longs
-  long Read(const char *szKey, long lDefault) const
+  virtual long Read(const char *szKey, long lDefault) const
     { long l; Read(&l, szKey, lDefault); return l; }
     // and another version: returns true if default value is returned
   virtual bool Read(long *pl, const char *szKey, long lDefault = 0) const = 0;
index a2bbecb415e2e7dc6938427d833c61489851e3cb..84a12b4754fa8a91c52a82c34e894aa6bbc92ab2 100644 (file)
 // ----------------------------------------------------------------------------
 
 /*
-  wxFileConfig derives from base Config and implements file based config class, 
+  wxFileConfig derives from base Config and implements file based config class,
   i.e. it uses ASCII disk files to store the information. These files are
-  alternatively called INI, .conf or .rc in the documentation. They are 
+  alternatively called INI, .conf or .rc in the documentation. They are
   organized in groups or sections, which can nest (i.e. a group contains
   subgroups, which contain their own subgroups &c). Each group has some
-  number of entries, which are "key = value" pairs. More precisely, the format 
+  number of entries, which are "key = value" pairs. More precisely, the format
   is:
 
   # comments are allowed after either ';' or '#' (Win/UNIX standard)
@@ -118,11 +118,16 @@ public:
   virtual bool GetFirstEntry(wxString& str, long& lIndex);
   virtual bool GetNextEntry (wxString& str, long& lIndex);
 
+  virtual bool HasGroup(const wxString& strName) const;
+  virtual bool HasEntry(const wxString& strName) const;
+
   virtual bool Read(wxString *pstr, const char *szKey,
                     const char *szDefault = 0) const;
   virtual const char *Read(const char *szKey,
                            const char *szDefault = 0) const;
   virtual bool Read(long *pl, const char *szKey, long lDefault) const;
+  virtual long Read(const char *szKey, long lDefault) const
+    { return wxConfig::Read(szKey, lDefault); }
   virtual bool Write(const char *szKey, const char *szValue);
   virtual bool Write(const char *szKey, long lValue);
   virtual bool Flush(bool bCurrentOnly = FALSE);
@@ -141,12 +146,14 @@ public:
   {
   public:
     // ctor
-    LineList(const wxString& str, LineList *pNext = NULL) : m_strLine(str) 
-      { SetNext(pNext); }
-    
-    // 
+    LineList(const wxString& str, LineList *pNext = NULL) : m_strLine(str)
+      { SetNext(pNext); SetPrev(NULL); }
+
+    //
     LineList *Next() const              { return m_pNext;  }
+    LineList *Prev() const              { return m_pPrev;  }
     void      SetNext(LineList *pNext)  { m_pNext = pNext; }
+    void      SetPrev(LineList *pPrev)  { m_pPrev = pPrev; }
 
     //
     void SetText(const wxString& str) { m_strLine = str;  }
@@ -154,13 +161,15 @@ public:
 
   private:
     wxString  m_strLine;      // line contents
-    LineList *m_pNext;        // next node
+    LineList *m_pNext,        // next node
+             *m_pPrev;        // previous one
   };
-  
+
   // functions to work with this list
   LineList *LineListAppend(const wxString& str);
-  LineList *LineListInsert(const wxString& str, 
-                           LineList *pLine);    // NULL => Append()
+  LineList *LineListInsert(const wxString& str,
+                           LineList *pLine);    // NULL => Prepend()
+  void      LineListRemove(LineList *pLine);
   bool      LineListIsEmpty();
 
 private:
@@ -268,7 +277,7 @@ protected:
     // will also recursively set parent's dirty flag
     void SetDirty();
     void SetLine(LineList *pLine);
-    
+
     // the new entries in this subgroup will be inserted after the last subgroup
     // or, if there is none, after the last entry
     void SetLastEntry(ConfigEntry *pLastEntry) { m_pLastEntry = pLastEntry; }
index 9f1aea52c0c85aa861a5f36352f0f8e4ad679bb5..f2e2c35e03f00524aafdf92a8818034f6fd78bf4 100644 (file)
@@ -2,7 +2,7 @@
 // Name:        fileconf.cpp
 // Purpose:     implementation of wxFileConfig derivation of wxConfig
 // Author:      Vadim Zeitlin
-// Modified by: 
+// Modified by:
 // Created:     07.04.98 (adapted from appconf.cpp)
 // RCS-ID:      $Id$
 // Copyright:   (c) 1997 Karsten Ballüder   &  Vadim Zeitlin
@@ -55,7 +55,7 @@
 // is 'c' a valid character in group name?
 // NB: APPCONF_IMMUTABLE_PREFIX and APPCONF_PATH_SEPARATOR must be valid chars,
 //     but _not_ ']' (group name delimiter)
-inline bool IsValid(char c) { return isalnum(c) || strchr("_/-!.*%", c); }
+inline bool IsValid(char c) { return isalnum(c) || strchr("@_/-!.*%", c); }
 
 // filter strings
 static wxString FilterIn(const wxString& str);
@@ -131,7 +131,7 @@ wxString wxFileConfig::GetLocalFileName(const char *szFile)
 
 void wxFileConfig::Init()
 {
-  m_pCurrentGroup = 
+  m_pCurrentGroup =
   m_pRootGroup    = new ConfigGroup(NULL, "", this);
 
   m_linesHead =
@@ -191,7 +191,7 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
 {
   const char *pStart;
   const char *pEnd;
-  
+
   for ( uint n = 0; n < file.GetLineCount(); n++ ) {
     // add the line to linked list
     if ( bLocal )
@@ -238,12 +238,12 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
           case ';':
             bCont = FALSE;
             break;
-        
+
           case ' ':
           case '\t':
             // ignore whitespace ('\n' impossible here)
             break;
-          
+
           default:
             wxLogWarning("file '%s', line %d: '%s' ignored after group header.",
                          file.GetName(), n + 1, pEnd);
@@ -259,7 +259,7 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
       wxString strKey(pStart, pEnd);
 
       // skip whitespace
-      while ( isspace(*pEnd) ) 
+      while ( isspace(*pEnd) )
         pEnd++;
 
       if ( *pEnd++ != '=' ) {
@@ -288,7 +288,7 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
           //  (c) key from global file now found in local one
           // which is exactly what we want.
           else if ( !bLocal || pEntry->IsLocal() ) {
-            wxLogWarning("file '%s', line %d: key '%s' was first found at line %d.", 
+            wxLogWarning("file '%s', line %d: key '%s' was first found at line %d.",
                          file.GetName(), n + 1, strKey.c_str(), pEntry->Line());
 
             if ( bLocal )
@@ -297,7 +297,7 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
         }
 
         // skip whitespace
-        while ( isspace(*pEnd) ) 
+        while ( isspace(*pEnd) )
           pEnd++;
 
         wxString strValue;
@@ -325,8 +325,10 @@ void wxFileConfig::SetPath(const wxString& strPath)
 {
   wxArrayString aParts;
 
-  if ( strPath.IsEmpty() )
+  if ( strPath.IsEmpty() ) {
+    SetRootPath();
     return;
+  }
 
   if ( strPath[0] == APPCONF_PATH_SEPARATOR ) {
     // absolute path
@@ -392,6 +394,26 @@ bool wxFileConfig::GetNextEntry (wxString& str, long& lIndex)
     return FALSE;
 }
 
+// ----------------------------------------------------------------------------
+// tests for existence
+// ----------------------------------------------------------------------------
+
+bool wxFileConfig::HasGroup(const wxString& strName) const
+{
+  PathChanger path(this, strName);
+
+  ConfigGroup *pGroup = m_pCurrentGroup->FindSubgroup(path.Name());
+  return pGroup != NULL;
+}
+
+bool wxFileConfig::HasEntry(const wxString& strName) const
+{
+  PathChanger path(this, strName);
+
+  ConfigEntry *pEntry = m_pCurrentGroup->FindEntry(path.Name());
+  return pEntry != NULL;
+}
+
 // ----------------------------------------------------------------------------
 // read/write values
 // ----------------------------------------------------------------------------
@@ -540,6 +562,7 @@ wxFileConfig::LineList *wxFileConfig::LineListAppend(const wxString& str)
   else {
     // adjust pointers
     m_linesTail->SetNext(pLine);
+    pLine->SetPrev(m_linesTail);
   }
 
   m_linesTail = pLine;
@@ -547,26 +570,49 @@ wxFileConfig::LineList *wxFileConfig::LineListAppend(const wxString& str)
 }
 
 // insert a new line after the given one or in the very beginning if !pLine
-wxFileConfig::LineList *wxFileConfig::LineListInsert(const wxString& str, 
+wxFileConfig::LineList *wxFileConfig::LineListInsert(const wxString& str,
                                                      LineList *pLine)
 {
   if ( pLine == m_linesTail )
     return LineListAppend(str);
 
-  LineList *pNewLine;
-  
+  LineList *pNewLine = new LineList(str);
   if ( pLine == NULL ) {
-    pNewLine = new LineList(str, m_linesHead);
+    // prepend to the list
+    pNewLine->SetNext(m_linesHead);
+    m_linesHead->SetPrev(pNewLine);
     m_linesHead = pNewLine;
   }
   else {
-    pNewLine = new LineList(str, pLine->Next());
+    // insert before pLine
+    LineList *pNext = pLine->Next();
+    pNewLine->SetNext(pNext);
+    pNewLine->SetPrev(pLine);
+    pNext->SetPrev(pNewLine);
     pLine->SetNext(pNewLine);
   }
 
   return pNewLine;
 }
 
+void wxFileConfig::LineListRemove(LineList *pLine)
+{
+  LineList *pPrev = pLine->Prev(),
+           *pNext = pLine->Next();
+  if ( pPrev == NULL ) {
+    // deleting the first entry
+    m_linesHead = pNext;
+  }
+  else {
+    // not the first entry
+    pPrev->SetNext(pNext);
+  }
+
+  pNext->SetPrev(pPrev);
+
+  delete pLine;
+}
+
 bool wxFileConfig::LineListIsEmpty()
 {
   return m_linesHead == NULL;
@@ -627,7 +673,7 @@ wxFileConfig::LineList *wxFileConfig::ConfigGroup::GetGroupLine()
     if ( Parent() != NULL ) {
       wxString strFullName;
       strFullName << "[" << GetFullName().c_str() + 1 << "]"; // +1: no '/'
-      m_pLine = m_pConfig->LineListInsert(strFullName, 
+      m_pLine = m_pConfig->LineListInsert(strFullName,
                                           Parent()->GetLastGroupLine());
       Parent()->SetLastGroup(this);
     }
@@ -755,7 +801,21 @@ bool wxFileConfig::ConfigGroup::DeleteSubgroup(const char *szName)
   if ( n == nCount )
     return FALSE;
 
-  delete m_aSubgroups[n];
+  nCount = m_aEntries.Count();
+  for ( n = 0; n < nCount; n++ ) {
+    LineList *pLine = m_aEntries[n]->GetLine();
+    if ( pLine != NULL )
+      m_pConfig->LineListRemove(pLine);
+  }
+
+  ConfigGroup *pGroup = m_aSubgroups[n];
+  LineList *pLine = pGroup->m_pLine;
+  if ( pLine != NULL )
+    m_pConfig->LineListRemove(pLine);
+  delete pGroup;
+
+  SetDirty();
+
   m_aSubgroups.Remove(n);
   return TRUE;
 }
@@ -771,13 +831,20 @@ bool wxFileConfig::ConfigGroup::DeleteEntry(const char *szName)
   if ( n == nCount )
     return FALSE;
 
-  delete m_aEntries[n];
+  ConfigEntry *pEntry = m_aEntries[n];
+  LineList *pLine = pEntry->GetLine();
+  if ( pLine != NULL )
+    m_pConfig->LineListRemove(pLine);
+  delete pEntry;
+
+  SetDirty();
+
   m_aEntries.Remove(n);
   return TRUE;
 }
 
 // ----------------------------------------------------------------------------
-// 
+//
 // ----------------------------------------------------------------------------
 void wxFileConfig::ConfigGroup::SetDirty()
 {
@@ -793,7 +860,7 @@ void wxFileConfig::ConfigGroup::SetDirty()
 // ----------------------------------------------------------------------------
 // ctor
 // ----------------------------------------------------------------------------
-wxFileConfig::ConfigEntry::ConfigEntry(wxFileConfig::ConfigGroup *pParent, 
+wxFileConfig::ConfigEntry::ConfigEntry(wxFileConfig::ConfigGroup *pParent,
                                        const wxString& strName,
                                        int nLine)
                          : m_strName(strName)
@@ -829,7 +896,7 @@ void wxFileConfig::ConfigEntry::SetLine(LineList *pLine)
 void wxFileConfig::ConfigEntry::SetValue(const wxString& strValue, bool bUser)
 {
   if ( bUser && IsImmutable() ) {
-    wxLogWarning("Attempt to change immutable key '%s' ignored.", 
+    wxLogWarning("Attempt to change immutable key '%s' ignored.",
                  Name().c_str());
     return;
   }
@@ -853,7 +920,7 @@ void wxFileConfig::ConfigEntry::SetValue(const wxString& strValue, bool bUser)
       // add a new line to the file
       wxASSERT( m_nLine == NOT_FOUND );   // consistency check
 
-      m_pLine = Group()->Config()->LineListInsert(strLine, 
+      m_pLine = Group()->Config()->LineListInsert(strLine,
                                                   Group()->GetLastEntryLine());
       Group()->SetLastEntry(this);
     }