Drawing correction
[wxWidgets.git] / src / common / fileconf.cpp
index f70b797e3fedec095d08fbe75e55289e1f13eece..7207637f634d54b4aef68f236e6f185f3d19964e 100644 (file)
@@ -30,6 +30,9 @@
     #include  "wx/log.h"
     #include  "wx/app.h"
     #include  "wx/utils.h"    // for wxGetHomeDir
+    #if wxUSE_STREAMS
+        #include  "wx/stream.h"
+    #endif // wxUSE_STREAMS
 #endif  //WX_PRECOMP
 
 #include  "wx/file.h"
 #include  "wx/fileconf.h"
 #include  "wx/filefn.h"
 
-#if wxUSE_STREAMS
-    #include  "wx/stream.h"
-#endif // wxUSE_STREAMS
-
-
 #if defined(__WXMAC__)
     #include  "wx/mac/private.h"  // includes mac headers
     #include  "wx/filename.h"     // for MacSetTypeAndCreator
@@ -330,12 +328,12 @@ wxString wxFileConfig::GetLocalDir()
     return strDir;
 }
 
-wxString wxFileConfig::GetGlobalFileName(const wxChar *szFile)
+wxString wxFileConfig::GetGlobalFileName(const wxString& file)
 {
     wxString str = GetGlobalDir();
-    str << szFile;
+    str << file;
 
-    if ( wxStrchr(szFile, wxT('.')) == NULL )
+    if ( wxStrchr(file, wxT('.')) == NULL )
 #if defined( __WXMAC__ )
         str << wxT(" Preferences") ;
 #elif defined( __UNIX__ )
@@ -347,7 +345,7 @@ wxString wxFileConfig::GetGlobalFileName(const wxChar *szFile)
     return str;
 }
 
-wxString wxFileConfig::GetLocalFileName(const wxChar *szFile)
+wxString wxFileConfig::GetLocalFileName(const wxString& file)
 {
 #ifdef __VMS__
     // On VMS I saw the problem that the home directory was appended
@@ -362,10 +360,10 @@ wxString wxFileConfig::GetLocalFileName(const wxChar *szFile)
     str << wxT('.');
 #endif
 
-    str << szFile;
+    str << file;
 
 #if defined(__WINDOWS__) || defined(__DOS__)
-    if ( wxStrchr(szFile, wxT('.')) == NULL )
+    if ( wxStrchr(file, wxT('.')) == NULL )
         str << wxT(".ini");
 #endif
 
@@ -437,7 +435,13 @@ wxFileConfig::wxFileConfig(const wxString& appName, const wxString& vendorName,
 {
     // Make up names for files if empty
     if ( m_strLocalFile.empty() && (style & wxCONFIG_USE_LOCAL_FILE) )
+    {
         m_strLocalFile = GetLocalFileName(GetAppName());
+#if defined(__UNIX__) && !defined(__VMS)
+        if ( style & wxCONFIG_USE_SUBDIR )
+            m_strLocalFile << wxFILE_SEP_PATH << GetAppName() << _T(".conf");
+#endif
+    }
 
     if ( m_strGlobalFile.empty() && (style & wxCONFIG_USE_GLOBAL_FILE) )
         m_strGlobalFile = GetGlobalFileName(GetAppName());
@@ -891,12 +895,44 @@ bool wxFileConfig::HasGroup(const wxString& strName) const
     return rc;
 }
 
-bool wxFileConfig::HasEntry(const wxString& strName) const
+bool wxFileConfig::HasEntry(const wxString& entry) const
 {
-    wxConfigPathChanger path(this, strName);
+    // path is the part before the last "/"
+    wxString path = entry.BeforeLast(wxCONFIG_PATH_SEPARATOR);
 
-    wxFileConfigEntry *pEntry = m_pCurrentGroup->FindEntry(path.Name());
-    return pEntry != NULL;
+    // except in the special case of "/keyname" when there is nothing before "/"
+    if ( path.empty() && *entry.c_str() == wxCONFIG_PATH_SEPARATOR )
+    {
+        path = wxCONFIG_PATH_SEPARATOR;
+    }
+
+    // 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);
+    if ( !path.empty() )
+    {
+        pathOld = GetPath();
+        if ( pathOld.empty() )
+            pathOld = wxCONFIG_PATH_SEPARATOR;
+
+        if ( !self->DoSetPath(path, false /* don't create if doesn't exist */) )
+        {
+            return false;
+        }
+    }
+
+    // check if the entry exists in this group
+    const bool exists = m_pCurrentGroup->FindEntry(
+                            entry.AfterLast(wxCONFIG_PATH_SEPARATOR)) != NULL;
+
+    // restore the old path if we changed it above
+    if ( !pathOld.empty() )
+    {
+        self->SetPath(pathOld);
+    }
+
+    return exists;
 }
 
 // ----------------------------------------------------------------------------
@@ -1011,15 +1047,17 @@ bool wxFileConfig::Flush(bool /* bCurrentOnly */)
   }
 
   // write all strings to file
+  wxString filetext;
+  filetext.reserve(4096);
   for ( wxFileConfigLineList *p = m_linesHead; p != NULL; p = p->Next() )
   {
-    wxString line = p->Text();
-    line += wxTextFile::GetEOL();
-    if ( !file.Write(line, *m_conv) )
-    {
-      wxLogError(_("can't write user configuration file."));
-      return false;
-    }
+    filetext << p->Text() << wxTextFile::GetEOL();
+  }
+
+  if ( !file.Write(filetext, *m_conv) )
+  {
+    wxLogError(_("can't write user configuration file."));
+    return false;
   }
 
   if ( !file.Commit() )
@@ -1142,11 +1180,13 @@ bool wxFileConfig::DeleteEntry(const wxString& key, bool bGroupIfEmptyAlso)
 
 bool wxFileConfig::DeleteGroup(const wxString& key)
 {
-  wxConfigPathChanger path(this, key);
+  wxConfigPathChanger path(this, RemoveTrailingSeparator(key));
 
   if ( !m_pCurrentGroup->DeleteSubgroupByName(path.Name()) )
       return false;
 
+  path.UpdateIfDeleted();
+
   SetDirty();
 
   return true;
@@ -1515,8 +1555,17 @@ void wxFileConfigGroup::Rename(const wxString& newName)
 {
     wxCHECK_RET( m_pParent, _T("the root group can't be renamed") );
 
+    if ( newName == m_strName )
+        return;
+
+    // we need to remove the group from the parent and it back under the new
+    // name to keep the parents array of subgroups alphabetically sorted
+    m_pParent->m_aSubgroups.Remove(this);
+
     m_strName = newName;
 
+    m_pParent->m_aSubgroups.Add(this);
+
     // update the group lines recursively
     UpdateGroupAndSubgroupsLines();
 }
@@ -1652,12 +1701,12 @@ bool wxFileConfigGroup::DeleteSubgroup(wxFileConfigGroup *pGroup)
 
     wxLogTrace( FILECONF_TRACE_MASK,
                 _T("  (m_pLine) = prev: %p, this %p, next %p"),
-                ((m_pLine) ? m_pLine->Prev() : 0),
-                m_pLine,
-                ((m_pLine) ? m_pLine->Next() : 0) );
+                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 );
     wxLogTrace( FILECONF_TRACE_MASK,
                 _T("  text: '%s'"),
-                ((m_pLine) ? m_pLine->Text().c_str() : wxEmptyString) );
+                m_pLine ? m_pLine->Text().c_str() : wxEmptyString );
 
     // delete all entries...
     size_t nCount = pGroup->m_aEntries.Count();