]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/fileconf.cpp
protect gs_allThreads with a mutex (modified patch 1518719)
[wxWidgets.git] / src / common / fileconf.cpp
index 3a25662db7c74018a7e7fe1474b205d347f5b66a..cc4823e0588b88c46e153a51c5972d4d51d53f2e 100644 (file)
 // headers
 // ----------------------------------------------------------------------------
 
+// For compilers that support precompilation, includes "wx.h".
 #include  "wx/wxprec.h"
 
 #ifdef    __BORLANDC__
-  #pragma hdrstop
+    #pragma hdrstop
 #endif  //__BORLANDC__
 
 #if wxUSE_CONFIG && wxUSE_FILECONFIG
 
 #ifndef   WX_PRECOMP
-  #include  "wx/string.h"
-  #include  "wx/intl.h"
+    #include  "wx/dynarray.h"
+    #include  "wx/string.h"
+    #include  "wx/intl.h"
+    #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/app.h"
-#include  "wx/dynarray.h"
 #include  "wx/file.h"
-#include  "wx/log.h"
 #include  "wx/textfile.h"
 #include  "wx/memtext.h"
 #include  "wx/config.h"
 #include  "wx/fileconf.h"
 #include  "wx/filefn.h"
 
-#if wxUSE_STREAMS
-    #include  "wx/stream.h"
-#endif // wxUSE_STREAMS
-
-#include  "wx/utils.h"    // for wxGetHomeDir
-
 #if defined(__WXMAC__)
-  #include  "wx/mac/private.h"  // includes mac headers
-  #include  "wx/filename.h"     // for MacSetTypeAndCreator
+    #include  "wx/mac/private.h"  // includes mac headers
+    #include  "wx/filename.h"     // for MacSetTypeAndCreator
 #endif
 
 #if defined(__WXMSW__)
-  #include "wx/msw/private.h"
+    #include "wx/msw/private.h"
 #endif  //windows.h
 #if defined(__WXPM__)
-  #define INCL_DOS
-  #include <os2.h>
+    #define INCL_DOS
+    #include <os2.h>
 #endif
 
 #include  <stdlib.h>
@@ -69,7 +68,7 @@
 // ----------------------------------------------------------------------------
 
 #ifndef MAX_PATH
-  #define MAX_PATH 512
+    #define MAX_PATH 512
 #endif
 
 #define FILECONF_TRACE_MASK _T("fileconf")
@@ -283,7 +282,7 @@ wxString wxFileConfig::GetGlobalDir()
         strDir.Printf(wxT("%c:\\OS2\\"), 'A'+drive-1);
     }
 #elif defined(__WXSTUBS__)
-    wxASSERT_MSG( false, wxT("TODO") ) ;
+    wxFAIL_MSG( wxT("TODO") );
 #elif defined(__DOS__)
     // There's no such thing as global cfg dir in MS-DOS, let's return
     // current directory (FIXME_MGL?)
@@ -308,18 +307,22 @@ wxString wxFileConfig::GetLocalDir()
 
 #if defined(__WXMAC__) || defined(__DOS__)
     // no local dir concept on Mac OS 9 or MS-DOS
-    return GetGlobalDir() ;
+    strDir << GetGlobalDir() ;
 #else
     wxGetHomeDir(&strDir);
 
-#ifdef  __UNIX__
-#ifdef __VMS
-    if (strDir.Last() != wxT(']'))
-#endif
-    if (strDir.Last() != wxT('/')) strDir << wxT('/');
-#else
-    if (strDir.Last() != wxT('\\')) strDir << wxT('\\');
-#endif
+    #ifdef  __UNIX__
+        if (
+            (strDir.Last() != wxT('/'))
+        #ifdef __VMS
+            && (strDir.Last() != wxT(']'))
+        #endif
+            )
+            strDir << wxT('/');
+    #else
+        if (strDir.Last() != wxT('\\'))
+            strDir << wxT('\\');
+    #endif
 #endif
 
     return strDir;
@@ -390,7 +393,7 @@ void wxFileConfig::Init()
     {
         wxTextFile fileGlobal(m_strGlobalFile);
 
-        if ( fileGlobal.Open(m_conv/*ignored in ANSI build*/) )
+        if ( fileGlobal.Open(*m_conv/*ignored in ANSI build*/) )
         {
             Parse(fileGlobal, false /* global */);
             SetRootPath();
@@ -405,7 +408,7 @@ void wxFileConfig::Init()
     if ( !m_strLocalFile.empty() && wxFile::Exists(m_strLocalFile) )
     {
         wxTextFile fileLocal(m_strLocalFile);
-        if ( fileLocal.Open(m_conv/*ignored in ANSI build*/) )
+        if ( fileLocal.Open(*m_conv/*ignored in ANSI build*/) )
         {
             Parse(fileLocal, true /* local */);
             SetRootPath();
@@ -422,12 +425,13 @@ void wxFileConfig::Init()
 // constructor supports creation of wxFileConfig objects of any type
 wxFileConfig::wxFileConfig(const wxString& appName, const wxString& vendorName,
                            const wxString& strLocal, const wxString& strGlobal,
-                           long style, wxMBConv& conv)
+                           long style,
+                           const wxMBConv& conv)
             : wxConfigBase(::GetAppName(appName), vendorName,
                            strLocal, strGlobal,
                            style),
               m_strLocalFile(strLocal), m_strGlobalFile(strGlobal),
-              m_conv(conv)
+              m_conv(conv.Clone())
 {
     // Make up names for files if empty
     if ( m_strLocalFile.empty() && (style & wxCONFIG_USE_LOCAL_FILE) )
@@ -470,8 +474,8 @@ wxFileConfig::wxFileConfig(const wxString& appName, const wxString& vendorName,
 
 #if wxUSE_STREAMS
 
-wxFileConfig::wxFileConfig(wxInputStream &inStream, wxMBConv& conv)
-            : m_conv(conv)
+wxFileConfig::wxFileConfig(wxInputStream &inStream, const wxMBConv& conv)
+            : m_conv(conv.Clone())
 {
     // always local_file when this constructor is called (?)
     SetStyle(GetStyle() | wxCONFIG_USE_LOCAL_FILE);
@@ -566,6 +570,8 @@ wxFileConfig::~wxFileConfig()
     Flush();
 
     CleanUp();
+
+    delete m_conv;
 }
 
 // ----------------------------------------------------------------------------
@@ -883,12 +889,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;
 }
 
 // ----------------------------------------------------------------------------
@@ -1007,7 +1045,7 @@ bool wxFileConfig::Flush(bool /* bCurrentOnly */)
   {
     wxString line = p->Text();
     line += wxTextFile::GetEOL();
-    if ( !file.Write(line, m_conv) )
+    if ( !file.Write(line, *m_conv) )
     {
       wxLogError(_("can't write user configuration file."));
       return false;
@@ -1032,7 +1070,7 @@ bool wxFileConfig::Flush(bool /* bCurrentOnly */)
 
 #if wxUSE_STREAMS
 
-bool wxFileConfig::Save(wxOutputStream& os, wxMBConv& conv)
+bool wxFileConfig::Save(wxOutputStream& os, const wxMBConv& conv)
 {
     // save unconditionally, even if not dirty
     for ( wxFileConfigLineList *p = m_linesHead; p != NULL; p = p->Next() )
@@ -1139,6 +1177,8 @@ bool wxFileConfig::DeleteGroup(const wxString& key)
   if ( !m_pCurrentGroup->DeleteSubgroupByName(path.Name()) )
       return false;
 
+  path.UpdateIfDeleted();
+
   SetDirty();
 
   return true;
@@ -1156,9 +1196,6 @@ bool wxFileConfig::DeleteAll()
                         m_strLocalFile.c_str());
           return false;
       }
-
-      m_strLocalFile =
-      m_strGlobalFile = wxEmptyString;
   }
 
   Init();
@@ -1647,12 +1684,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();
@@ -1897,20 +1934,20 @@ void wxFileConfigEntry::SetValue(const wxString& strValue, bool bUser)
 
 int CompareEntries(wxFileConfigEntry *p1, wxFileConfigEntry *p2)
 {
-  #if wxCONFIG_CASE_SENSITIVE
+#if wxCONFIG_CASE_SENSITIVE
     return wxStrcmp(p1->Name(), p2->Name());
-  #else
+#else
     return wxStricmp(p1->Name(), p2->Name());
-  #endif
+#endif
 }
 
 int CompareGroups(wxFileConfigGroup *p1, wxFileConfigGroup *p2)
 {
-  #if wxCONFIG_CASE_SENSITIVE
+#if wxCONFIG_CASE_SENSITIVE
     return wxStrcmp(p1->Name(), p2->Name());
-  #else
+#else
     return wxStricmp(p1->Name(), p2->Name());
-  #endif
+#endif
 }
 
 // ----------------------------------------------------------------------------
@@ -2026,8 +2063,11 @@ static wxString FilterInEntryName(const wxString& str)
   strResult.Alloc(str.Len());
 
   for ( const wxChar *pc = str.c_str(); *pc != '\0'; pc++ ) {
-    if ( *pc == wxT('\\') )
-      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') )
+        break;
+    }
 
     strResult += *pc;
   }