]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/fileconf.cpp
Fix for #15520: wxRichTextCtrl: Drawing the selection doesn't respect its container...
[wxWidgets.git] / src / common / fileconf.cpp
index 07da5e6ff2874f585bee22af703840078c4ff936..e626c3c0ccf5bed80f729b3c309bbb3ba2d0e24b 100644 (file)
@@ -4,8 +4,7 @@
 // Author:      Vadim Zeitlin
 // Modified by:
 // Created:     07.04.98 (adapted from appconf.cpp)
-// RCS-ID:      $Id$
-// Copyright:   (c) 1997 Karsten Ballüder   &  Vadim Zeitlin
+// Copyright:   (c) 1997 Karsten Ballueder  &  Vadim Zeitlin
 //                       Ballueder@usa.net     <zeitlin@dptmaths.ens-cachan.fr>
 // Licence:     wxWindows licence
 ///////////////////////////////////////////////////////////////////////////////
 
 #include  "wx/stdpaths.h"
 
-#if defined(__WXMAC__)
-    #include  "wx/mac/private.h"  // includes mac headers
-#endif
-
-#if defined(__WXMSW__)
+#if defined(__WINDOWS__)
     #include "wx/msw/private.h"
 #endif  //windows.h
 #if defined(__WXPM__)
 #include  <stdlib.h>
 #include  <ctype.h>
 
-// ----------------------------------------------------------------------------
-// macros
-// ----------------------------------------------------------------------------
-#define CONST_CAST ((wxFileConfig *)this)->
-
 // ----------------------------------------------------------------------------
 // constants
 // ----------------------------------------------------------------------------
@@ -74,7 +64,7 @@
     #define MAX_PATH 512
 #endif
 
-#define FILECONF_TRACE_MASK _T("fileconf")
+#define FILECONF_TRACE_MASK wxT("fileconf")
 
 // ----------------------------------------------------------------------------
 // global functions declarations
@@ -141,7 +131,7 @@ private:
   wxFileConfigLineList *m_pNext,        // next node
                        *m_pPrev;        // previous one
 
-    DECLARE_NO_COPY_CLASS(wxFileConfigLineList)
+    wxDECLARE_NO_COPY_CLASS(wxFileConfigLineList);
 };
 
 // ----------------------------------------------------------------------------
@@ -155,7 +145,7 @@ private:
 
   wxString      m_strName,      // entry name
                 m_strValue;     //       value
-  bool          m_bImmutable:1, // can be overriden locally?
+  bool          m_bImmutable:1, // can be overridden locally?
                 m_bHasValue:1;  // set after first call to SetValue()
 
   int           m_nLine;        // used if m_pLine == NULL only
@@ -182,7 +172,7 @@ public:
   void SetValue(const wxString& strValue, bool bUser = true);
   void SetLine(wxFileConfigLineList *pLine);
 
-    DECLARE_NO_COPY_CLASS(wxFileConfigEntry)
+    wxDECLARE_NO_COPY_CLASS(wxFileConfigEntry);
 };
 
 // ----------------------------------------------------------------------------
@@ -245,6 +235,7 @@ public:
 
   // get the last line belonging to an entry/subgroup of this group
   wxFileConfigLineList *GetGroupLine();     // line which contains [group]
+                                            // may be NULL for "/" only
   wxFileConfigLineList *GetLastEntryLine(); // after which our subgroups start
   wxFileConfigLineList *GetLastGroupLine(); // after which the next group starts
 
@@ -253,7 +244,7 @@ public:
   void SetLastGroup(wxFileConfigGroup *pGroup)
     { m_pLastGroup = pGroup; }
 
-  DECLARE_NO_COPY_CLASS(wxFileConfigGroup)
+  wxDECLARE_NO_COPY_CLASS(wxFileConfigGroup);
 };
 
 // ============================================================================
@@ -277,9 +268,9 @@ static void AddConfFileExtIfNeeded(wxFileName& fn)
 #if defined( __WXMAC__ )
         fn.SetName(fn.GetName() + wxT(" Preferences"));
 #elif defined( __UNIX__ )
-        fn.SetExt(wxT(".conf"));
+        fn.SetExt(wxT("conf"));
 #else   // Windows
-        fn.SetExt(wxT(".ini"));
+        fn.SetExt(wxT("ini"));
 #endif  // UNIX/Win
     }
 }
@@ -314,7 +305,7 @@ wxFileName wxFileConfig::GetLocalFile(const wxString& szFile, int style)
 {
     wxFileName fn(GetLocalDir(style), szFile);
 
-#ifdef __UNIX__
+#if defined( __UNIX__ ) && !defined( __WXMAC__ )
     if ( !(style & wxCONFIG_USE_SUBDIR) )
     {
         // dot-files under Unix start with, well, a dot (but OTOH they usually
@@ -322,7 +313,7 @@ wxFileName wxFileConfig::GetLocalFile(const wxString& szFile, int style)
         fn.SetName(wxT('.') + fn.GetName());
     }
     else // we do append ".conf" extension to config files in subdirectories
-#endif // __UNIX__
+#endif // defined( __UNIX__ ) && !defined( __WXMAC__ )
     {
         AddConfFileExtIfNeeded(fn);
     }
@@ -474,35 +465,38 @@ wxFileConfig::wxFileConfig(wxInputStream &inStream, const wxMBConv& conv)
     }
 #else // !wxUSE_UNICODE
     // no need for conversion
-    cbuf = wxCharBuffer::CreateNonOwned((char *)buf.GetData());
+    cbuf = wxCharBuffer::CreateNonOwned((char *)buf.GetData(), buf.GetDataLen());
 #endif // wxUSE_UNICODE/!wxUSE_UNICODE
 
-
-    // now break it into lines
-    wxMemoryText memText;
-    for ( const wxChar *s = cbuf; ; ++s )
+    // parse the input contents if there is anything to parse
+    if ( cbuf )
     {
-        const wxChar *e = s;
-        while ( *e != '\0' && *e != '\n' && *e != '\r' )
-            ++e;
+        // now break it into lines
+        wxMemoryText memText;
+        for ( const wxChar *s = cbuf; ; ++s )
+        {
+            const wxChar *e = s;
+            while ( *e != '\0' && *e != '\n' && *e != '\r' )
+                ++e;
 
-        // notice that we throw away the original EOL kind here, maybe we
-        // should preserve it?
-        if ( e != s )
-            memText.AddLine(wxString(s, e));
+            // notice that we throw away the original EOL kind here, maybe we
+            // should preserve it?
+            if ( e != s )
+                memText.AddLine(wxString(s, e));
 
-        if ( *e == '\0' )
-            break;
+            if ( *e == '\0' )
+                break;
 
-        // skip the second EOL byte if it's a DOS one
-        if ( *e == '\r' && e[1] == '\n' )
-            ++e;
+            // skip the second EOL byte if it's a DOS one
+            if ( *e == '\r' && e[1] == '\n' )
+                ++e;
 
-        s = e;
-    }
+            s = e;
+        }
 
-    // Finally we can parse it all.
-    Parse(memText, true /* local */);
+        // Finally we can parse it all.
+        Parse(memText, true /* local */);
+    }
 
     SetRootPath();
     ResetDirty();
@@ -550,16 +544,8 @@ void wxFileConfig::Parse(const wxTextBuffer& buffer, bool bLocal)
 
     // add the line to linked list
     if ( bLocal )
-    {
       LineListAppend(strLine);
 
-      // let the root group have its start line as well
-      if ( !n )
-      {
-        m_pCurrentGroup->SetLine(m_linesTail);
-      }
-    }
-
 
     // skip leading spaces
     for ( pStart = buf; wxIsspace(*pStart); pStart++ )
@@ -674,7 +660,7 @@ void wxFileConfig::Parse(const wxTextBuffer& buffer, bool bLocal)
           // which is exactly what we want.
           else if ( !bLocal || pEntry->IsLocal() ) {
             wxLogWarning(_("file '%s', line %d: key '%s' was first found at line %d."),
-                         buffer.GetName(), n + 1, strKey.c_str(), pEntry->Line());
+                         buffer.GetName(), (int)n + 1, strKey.c_str(), pEntry->Line());
 
           }
         }
@@ -757,6 +743,11 @@ void wxFileConfig::SetPath(const wxString& strPath)
     DoSetPath(strPath, true /* create missing path components */);
 }
 
+const wxString& wxFileConfig::GetPath() const
+{
+    return m_strPath;
+}
+
 // ----------------------------------------------------------------------------
 // enumeration
 // ----------------------------------------------------------------------------
@@ -797,12 +788,14 @@ size_t wxFileConfig::GetNumberOfEntries(bool bRecursive) const
 {
     size_t n = m_pCurrentGroup->Entries().GetCount();
     if ( bRecursive ) {
+        wxFileConfig * const self = const_cast<wxFileConfig *>(this);
+
         wxFileConfigGroup *pOldCurrentGroup = m_pCurrentGroup;
         size_t nSubgroups = m_pCurrentGroup->Groups().GetCount();
         for ( size_t nGroup = 0; nGroup < nSubgroups; nGroup++ ) {
-            CONST_CAST m_pCurrentGroup = m_pCurrentGroup->Groups()[nGroup];
+            self->m_pCurrentGroup = m_pCurrentGroup->Groups()[nGroup];
             n += GetNumberOfEntries(true);
-            CONST_CAST m_pCurrentGroup = pOldCurrentGroup;
+            self->m_pCurrentGroup = pOldCurrentGroup;
         }
     }
 
@@ -813,12 +806,14 @@ size_t wxFileConfig::GetNumberOfGroups(bool bRecursive) const
 {
     size_t n = m_pCurrentGroup->Groups().GetCount();
     if ( bRecursive ) {
+        wxFileConfig * const self = const_cast<wxFileConfig *>(this);
+
         wxFileConfigGroup *pOldCurrentGroup = m_pCurrentGroup;
         size_t nSubgroups = m_pCurrentGroup->Groups().GetCount();
         for ( size_t nGroup = 0; nGroup < nSubgroups; nGroup++ ) {
-            CONST_CAST m_pCurrentGroup = m_pCurrentGroup->Groups()[nGroup];
+            self->m_pCurrentGroup = m_pCurrentGroup->Groups()[nGroup];
             n += GetNumberOfGroups(true);
-            CONST_CAST m_pCurrentGroup = pOldCurrentGroup;
+            self->m_pCurrentGroup = pOldCurrentGroup;
         }
     }
 
@@ -838,7 +833,7 @@ bool wxFileConfig::HasGroup(const wxString& strName) const
 
     const wxString pathOld = GetPath();
 
-    wxFileConfig *self = wx_const_cast(wxFileConfig *, this);
+    wxFileConfig *self = const_cast<wxFileConfig *>(this);
     const bool
         rc = self->DoSetPath(strName, false /* don't create missing components */);
 
@@ -861,7 +856,7 @@ bool wxFileConfig::HasEntry(const wxString& entry) const
     // change to the path of the entry if necessary and remember the old path
     // to restore it later
     wxString pathOld;
-    wxFileConfig * const self = wx_const_cast(wxFileConfig *, this);
+    wxFileConfig * const self = const_cast<wxFileConfig *>(this);
     if ( !path.empty() )
     {
         pathOld = GetPath();
@@ -921,13 +916,13 @@ bool wxFileConfig::DoReadLong(const wxString& key, long *pl) const
 
 bool wxFileConfig::DoReadBinary(const wxString& key, wxMemoryBuffer* buf) const
 {
-    wxCHECK_MSG( buf, false, _T("NULL buffer") );
+    wxCHECK_MSG( buf, false, wxT("NULL buffer") );
 
     wxString str;
     if ( !Read(key, &str) )
         return false;
 
-    *buf = wxBase64Decode(str.ToAscii());
+    *buf = wxBase64Decode(str);
     return true;
 }
 
@@ -939,7 +934,7 @@ bool wxFileConfig::DoWriteString(const wxString& key, const wxString& szValue)
     wxString                strName = path.Name();
 
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("  Writing String '%s' = '%s' to Group '%s'"),
+                wxT("  Writing String '%s' = '%s' to Group '%s'"),
                 strName.c_str(),
                 szValue.c_str(),
                 GetPath().c_str() );
@@ -953,13 +948,13 @@ bool wxFileConfig::DoWriteString(const wxString& key, const wxString& szValue)
             // ... except if it's empty in which case it's a way to force it's creation
 
         wxLogTrace( FILECONF_TRACE_MASK,
-                    _T("  Creating group %s"),
+                    wxT("  Creating group %s"),
                     m_pCurrentGroup->Name().c_str() );
 
         SetDirty();
 
-            // this will add a line for this group if it didn't have it before
-
+        // this will add a line for this group if it didn't have it before (or
+        // do nothing for the root but it's ok as it always exists anyhow)
         (void)m_pCurrentGroup->GetGroupLine();
     }
     else
@@ -977,13 +972,13 @@ bool wxFileConfig::DoWriteString(const wxString& key, const wxString& szValue)
         if ( pEntry == 0 )
         {
             wxLogTrace( FILECONF_TRACE_MASK,
-                        _T("  Adding Entry %s"),
+                        wxT("  Adding Entry %s"),
                         strName.c_str() );
             pEntry = m_pCurrentGroup->AddEntry(strName);
         }
 
         wxLogTrace( FILECONF_TRACE_MASK,
-                    _T("  Setting value %s"),
+                    wxT("  Setting value %s"),
                     szValue.c_str() );
         pEntry->SetValue(szValue);
 
@@ -995,7 +990,7 @@ bool wxFileConfig::DoWriteString(const wxString& key, const wxString& szValue)
 
 bool wxFileConfig::DoWriteLong(const wxString& key, long lValue)
 {
-  return Write(key, wxString::Format(_T("%ld"), lValue));
+  return Write(key, wxString::Format(wxT("%ld"), lValue));
 }
 
 #if wxUSE_BASE64
@@ -1046,7 +1041,7 @@ bool wxFileConfig::Flush(bool /* bCurrentOnly */)
 
   ResetDirty();
 
-#if defined(__WXMAC__)
+#if defined( __WXOSX_MAC__ ) && wxOSX_USE_CARBON
   m_fnLocalFile.MacSetTypeAndCreator('TEXT', 'ttxt');
 #endif // __WXMAC__
 
@@ -1087,7 +1082,7 @@ bool wxFileConfig::RenameEntry(const wxString& oldName,
                                const wxString& newName)
 {
     wxASSERT_MSG( oldName.find(wxCONFIG_PATH_SEPARATOR) == wxString::npos,
-                   _T("RenameEntry(): paths are not supported") );
+                   wxT("RenameEntry(): paths are not supported") );
 
     // check that the entry exists
     wxFileConfigEntry *oldEntry = m_pCurrentGroup->FindEntry(oldName);
@@ -1198,14 +1193,14 @@ bool wxFileConfig::DeleteAll()
 wxFileConfigLineList *wxFileConfig::LineListAppend(const wxString& str)
 {
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("    ** Adding Line '%s'"),
+                wxT("    ** Adding Line '%s'"),
                 str.c_str() );
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("        head: %s"),
+                wxT("        head: %s"),
                 ((m_linesHead) ? (const wxChar*)m_linesHead->Text().c_str()
                                : wxEmptyString) );
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("        tail: %s"),
+                wxT("        tail: %s"),
                 ((m_linesTail) ? (const wxChar*)m_linesTail->Text().c_str()
                                : wxEmptyString) );
 
@@ -1226,11 +1221,11 @@ wxFileConfigLineList *wxFileConfig::LineListAppend(const wxString& str)
     m_linesTail = pLine;
 
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("        head: %s"),
+                wxT("        head: %s"),
                 ((m_linesHead) ? (const wxChar*)m_linesHead->Text().c_str()
                                : wxEmptyString) );
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("        tail: %s"),
+                wxT("        tail: %s"),
                 ((m_linesTail) ? (const wxChar*)m_linesTail->Text().c_str()
                                : wxEmptyString) );
 
@@ -1242,16 +1237,16 @@ wxFileConfigLineList *wxFileConfig::LineListInsert(const wxString& str,
                                                    wxFileConfigLineList *pLine)
 {
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("    ** Inserting Line '%s' after '%s'"),
+                wxT("    ** Inserting Line '%s' after '%s'"),
                 str.c_str(),
                 ((pLine) ? (const wxChar*)pLine->Text().c_str()
                          : wxEmptyString) );
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("        head: %s"),
+                wxT("        head: %s"),
                 ((m_linesHead) ? (const wxChar*)m_linesHead->Text().c_str()
                                : wxEmptyString) );
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("        tail: %s"),
+                wxT("        tail: %s"),
                 ((m_linesTail) ? (const wxChar*)m_linesTail->Text().c_str()
                                : wxEmptyString) );
 
@@ -1277,11 +1272,11 @@ wxFileConfigLineList *wxFileConfig::LineListInsert(const wxString& str,
     }
 
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("        head: %s"),
+                wxT("        head: %s"),
                 ((m_linesHead) ? (const wxChar*)m_linesHead->Text().c_str()
                                : wxEmptyString) );
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("        tail: %s"),
+                wxT("        tail: %s"),
                 ((m_linesTail) ? (const wxChar*)m_linesTail->Text().c_str()
                                : wxEmptyString) );
 
@@ -1291,14 +1286,14 @@ wxFileConfigLineList *wxFileConfig::LineListInsert(const wxString& str,
 void wxFileConfig::LineListRemove(wxFileConfigLineList *pLine)
 {
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("    ** Removing Line '%s'"),
+                wxT("    ** Removing Line '%s'"),
                 pLine->Text().c_str() );
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("        head: %s"),
+                wxT("        head: %s"),
                 ((m_linesHead) ? (const wxChar*)m_linesHead->Text().c_str()
                                : wxEmptyString) );
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("        tail: %s"),
+                wxT("        tail: %s"),
                 ((m_linesTail) ? (const wxChar*)m_linesTail->Text().c_str()
                                : wxEmptyString) );
 
@@ -1319,15 +1314,12 @@ 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"),
+                wxT("        head: %s"),
                 ((m_linesHead) ? (const wxChar*)m_linesHead->Text().c_str()
                                : wxEmptyString) );
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("        tail: %s"),
+                wxT("        tail: %s"),
                 ((m_linesTail) ? (const wxChar*)m_linesTail->Text().c_str()
                                : wxEmptyString) );
 
@@ -1386,7 +1378,7 @@ void wxFileConfigGroup::SetLine(wxFileConfigLineList *pLine)
     // 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?") );
+                   wxT("changing line for a non-root group?") );
 
     m_pLine = pLine;
 }
@@ -1428,13 +1420,13 @@ void wxFileConfigGroup::SetLine(wxFileConfigLineList *pLine)
 wxFileConfigLineList *wxFileConfigGroup::GetGroupLine()
 {
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("  GetGroupLine() for Group '%s'"),
+                wxT("  GetGroupLine() for Group '%s'"),
                 Name().c_str() );
 
     if ( !m_pLine )
     {
         wxLogTrace( FILECONF_TRACE_MASK,
-                    _T("    Getting Line item pointer") );
+                    wxT("    Getting Line item pointer") );
 
         wxFileConfigGroup   *pParent = Parent();
 
@@ -1442,7 +1434,7 @@ wxFileConfigLineList *wxFileConfigGroup::GetGroupLine()
         if ( pParent )
         {
             wxLogTrace( FILECONF_TRACE_MASK,
-                        _T("    checking parent '%s'"),
+                        wxT("    checking parent '%s'"),
                         pParent->Name().c_str() );
 
             wxString    strFullName;
@@ -1473,7 +1465,7 @@ wxFileConfigLineList *wxFileConfigGroup::GetLastGroupLine()
     {
         wxFileConfigLineList *pLine = m_pLastGroup->GetLastGroupLine();
 
-        wxASSERT_MSG( pLine, _T("last group must have !NULL associated line") );
+        wxASSERT_MSG( pLine, wxT("last group must have !NULL associated line") );
 
         return pLine;
     }
@@ -1488,14 +1480,14 @@ wxFileConfigLineList *wxFileConfigGroup::GetLastGroupLine()
 wxFileConfigLineList *wxFileConfigGroup::GetLastEntryLine()
 {
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("  GetLastEntryLine() for Group '%s'"),
+                wxT("  GetLastEntryLine() for Group '%s'"),
                 Name().c_str() );
 
     if ( m_pLastEntry )
     {
         wxFileConfigLineList    *pLine = m_pLastEntry->GetLine();
 
-        wxASSERT_MSG( pLine, _T("last entry must have !NULL associated line") );
+        wxASSERT_MSG( pLine, wxT("last entry must have !NULL associated line") );
 
         return pLine;
     }
@@ -1513,7 +1505,7 @@ void wxFileConfigGroup::SetLastEntry(wxFileConfigEntry *pEntry)
         // the only situation in which a group without its own line can have
         // an entry is when the first entry is added to the initially empty
         // root pseudo-group
-        wxASSERT_MSG( !m_pParent, _T("unexpected for non root group") );
+        wxASSERT_MSG( !m_pParent, wxT("unexpected for non root group") );
 
         // let the group know that it does have a line in the file now
         m_pLine = pEntry->GetLine();
@@ -1528,10 +1520,10 @@ void wxFileConfigGroup::UpdateGroupAndSubgroupsLines()
 {
     // update the line of this group
     wxFileConfigLineList *line = GetGroupLine();
-    wxCHECK_RET( line, _T("a non root group must have a corresponding line!") );
+    wxCHECK_RET( line, wxT("a non root group must have a corresponding line!") );
 
     // +1: skip the leading '/'
-    line->SetText(wxString::Format(_T("[%s]"), GetFullName().c_str() + 1));
+    line->SetText(wxString::Format(wxT("[%s]"), GetFullName().c_str() + 1));
 
 
     // also update all subgroups as they have this groups name in their lines
@@ -1544,7 +1536,7 @@ void wxFileConfigGroup::UpdateGroupAndSubgroupsLines()
 
 void wxFileConfigGroup::Rename(const wxString& newName)
 {
-    wxCHECK_RET( m_pParent, _T("the root group can't be renamed") );
+    wxCHECK_RET( m_pParent, wxT("the root group can't be renamed") );
 
     if ( newName == m_strName )
         return;
@@ -1683,20 +1675,20 @@ bool wxFileConfigGroup::DeleteSubgroupByName(const wxString& name)
 // other data structures.
 bool wxFileConfigGroup::DeleteSubgroup(wxFileConfigGroup *pGroup)
 {
-    wxCHECK_MSG( pGroup, false, _T("deleting non existing group?") );
+    wxCHECK_MSG( pGroup, false, wxT("deleting non existing group?") );
 
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("Deleting group '%s' from '%s'"),
+                wxT("Deleting group '%s' from '%s'"),
                 pGroup->Name().c_str(),
                 Name().c_str() );
 
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("  (m_pLine) = prev: %p, this %p, next %p"),
-                m_pLine ? wx_static_cast(void*, m_pLine->Prev()) : 0,
-                wx_static_cast(void*, m_pLine),
-                m_pLine ? wx_static_cast(void*, m_pLine->Next()) : 0 );
+                wxT("  (m_pLine) = prev: %p, this %p, next %p"),
+                m_pLine ? static_cast<void*>(m_pLine->Prev()) : 0,
+                static_cast<void*>(m_pLine),
+                m_pLine ? static_cast<void*>(m_pLine->Next()) : 0 );
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("  text: '%s'"),
+                wxT("  text: '%s'"),
                 m_pLine ? (const wxChar*)m_pLine->Text().c_str()
                         : wxEmptyString );
 
@@ -1704,7 +1696,7 @@ bool wxFileConfigGroup::DeleteSubgroup(wxFileConfigGroup *pGroup)
     size_t nCount = pGroup->m_aEntries.GetCount();
 
     wxLogTrace(FILECONF_TRACE_MASK,
-               _T("Removing %lu entries"), (unsigned long)nCount );
+               wxT("Removing %lu entries"), (unsigned long)nCount );
 
     for ( size_t nEntry = 0; nEntry < nCount; nEntry++ )
     {
@@ -1713,7 +1705,7 @@ bool wxFileConfigGroup::DeleteSubgroup(wxFileConfigGroup *pGroup)
         if ( pLine )
         {
             wxLogTrace( FILECONF_TRACE_MASK,
-                        _T("    '%s'"),
+                        wxT("    '%s'"),
                         pLine->Text().c_str() );
             m_pConfig->LineListRemove(pLine);
         }
@@ -1723,7 +1715,7 @@ bool wxFileConfigGroup::DeleteSubgroup(wxFileConfigGroup *pGroup)
     nCount = pGroup->m_aSubgroups.GetCount();
 
     wxLogTrace( FILECONF_TRACE_MASK,
-                _T("Removing %lu subgroups"), (unsigned long)nCount );
+                wxT("Removing %lu subgroups"), (unsigned long)nCount );
 
     for ( size_t nGroup = 0; nGroup < nCount; nGroup++ )
     {
@@ -1735,11 +1727,11 @@ bool wxFileConfigGroup::DeleteSubgroup(wxFileConfigGroup *pGroup)
     if ( pLine )
     {
         wxLogTrace( FILECONF_TRACE_MASK,
-                    _T("  Removing line for group '%s' : '%s'"),
+                    wxT("  Removing line for group '%s' : '%s'"),
                     pGroup->Name().c_str(),
                     pLine->Text().c_str() );
         wxLogTrace( FILECONF_TRACE_MASK,
-                    _T("  Removing from group '%s' : '%s'"),
+                    wxT("  Removing from group '%s' : '%s'"),
                     Name().c_str(),
                     ((m_pLine) ? (const wxChar*)m_pLine->Text().c_str()
                                : wxEmptyString) );
@@ -1749,7 +1741,7 @@ bool wxFileConfigGroup::DeleteSubgroup(wxFileConfigGroup *pGroup)
         if ( pGroup == m_pLastGroup )
         {
             wxLogTrace( FILECONF_TRACE_MASK,
-                        _T("  Removing last group") );
+                        wxT("  Removing last group") );
 
             // our last entry is being deleted, so find the last one which
             // stays by going back until we find a subgroup or reach the
@@ -1783,7 +1775,7 @@ bool wxFileConfigGroup::DeleteSubgroup(wxFileConfigGroup *pGroup)
     else
     {
         wxLogTrace( FILECONF_TRACE_MASK,
-                    _T("  No line entry for Group '%s'?"),
+                    wxT("  No line entry for Group '%s'?"),
                     pGroup->Name().c_str() );
     }
 
@@ -1810,29 +1802,26 @@ bool wxFileConfigGroup::DeleteEntry(const wxString& name)
       // our last entry is being deleted - find the last one which stays
       wxASSERT( m_pLine != NULL );  // if we have an entry with !NULL pLine...
 
-      // go back until we find another entry or reach the group's line
+      // find the previous entry (if any)
       wxFileConfigEntry *pNewLast = NULL;
-      size_t n, nEntries = m_aEntries.GetCount();
-      wxFileConfigLineList *pl;
-      for ( pl = pLine->Prev(); pl != m_pLine; pl = pl->Prev() ) {
-        // is it our subgroup?
-        for ( n = 0; (pNewLast == NULL) && (n < nEntries); n++ ) {
-          if ( m_aEntries[n]->GetLine() == m_pLine )
-            pNewLast = m_aEntries[n];
-        }
-
-        if ( pNewLast != NULL ) // found?
+      const wxFileConfigLineList * const
+        pNewLastLine = m_pLastEntry->GetLine()->Prev();
+      const size_t nEntries = m_aEntries.GetCount();
+      for ( size_t n = 0; n < nEntries; n++ ) {
+        if ( m_aEntries[n]->GetLine() == pNewLastLine ) {
+          pNewLast = m_aEntries[n];
           break;
+        }
       }
 
-      if ( pl == m_pLine ) {
-        wxASSERT( !pNewLast );  // how comes it has the same line as we?
+      // pNewLast can be NULL here -- it's ok and can happen if we have no
+      // entries left
+      m_pLastEntry = pNewLast;
 
-        // we've reached the group line without finding any subgroups
-        m_pLastEntry = NULL;
-      }
-      else
-        m_pLastEntry = pNewLast;
+      // For the root group only, we could be removing the first group line
+      // here, so update m_pLine to avoid keeping a dangling pointer.
+      if ( pLine == m_pLine )
+          SetLine(NULL);
     }
 
     m_pConfig->LineListRemove(pLine);
@@ -2097,7 +2086,7 @@ static wxString FilterInEntryName(const wxString& str)
   for ( const wxChar *pc = str.c_str(); *pc != '\0'; pc++ ) {
     if ( *pc == wxT('\\') ) {
       // we need to test it here or we'd skip past the NUL in the loop line
-      if ( *++pc == _T('\0') )
+      if ( *++pc == wxT('\0') )
         break;
     }
 
@@ -2126,7 +2115,7 @@ static wxString FilterOutEntryName(const wxString& str)
 #if !wxUSE_UNICODE
             ((unsigned char)c < 127) &&
 #endif // ANSI
-         !wxIsalnum(c) && !wxStrchr(wxT("@_/-!.*%"), c) )
+         !wxIsalnum(c) && !wxStrchr(wxT("@_/-!.*%()"), c) )
     {
       strResult += wxT('\\');
     }