]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/fileconf.cpp
Applied patch [ 605189 ] add edit cancel notify to wxTreeEvent
[wxWidgets.git] / src / common / fileconf.cpp
index 256655447aed5ee72d692577cb31666600b9ce94..5ef534169bda8a955d7a290a25fbf27f4c4c2bec 100644 (file)
 #include  "wx/file.h"
 #include  "wx/log.h"
 #include  "wx/textfile.h"
+#include  "wx/memtext.h"
 #include  "wx/config.h"
 #include  "wx/fileconf.h"
 
+#if wxUSE_STREAMS
+    #include  "wx/stream.h"
+#endif // wxUSE_STREAMS
+
 #include  "wx/utils.h"    // for wxGetHomeDir
 
-// _WINDOWS_ is defined when windows.h is included,
-// __WXMSW__ is defined for MS Windows compilation
-#if       defined(__WXMSW__) && !defined(_WINDOWS_)
-  #include  <windows.h>
+#if defined(__WXMAC__)
+  #include  "wx/mac/private.h"  // includes mac headers
+#endif
+
+#if defined(__WXMSW__)
+  #include "wx/msw/private.h"
 #endif  //windows.h
 #if defined(__WXPM__)
   #define INCL_DOS
@@ -99,8 +106,8 @@ static wxString GetAppName(const wxString& appname);
 // "template" array types
 // ----------------------------------------------------------------------------
 
-WX_DEFINE_SORTED_ARRAY(wxFileConfigEntry *, ArrayEntries);
-WX_DEFINE_SORTED_ARRAY(wxFileConfigGroup *, ArrayGroups);
+WX_DEFINE_SORTED_EXPORTED_ARRAY(wxFileConfigEntry *, ArrayEntries);
+WX_DEFINE_SORTED_EXPORTED_ARRAY(wxFileConfigGroup *, ArrayGroups);
 
 // ----------------------------------------------------------------------------
 // wxFileConfigLineList
@@ -256,6 +263,8 @@ wxString wxFileConfig::GetGlobalDir()
 
   #ifdef __VMS__ // Note if __VMS is defined __UNIX is also defined
     strDir = wxT("sys$manager:");
+  #elif defined(__WXMAC__)
+    strDir = wxMacFindFolder(  (short) kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder ) ;
   #elif defined( __UNIX__ )
     strDir = wxT("/etc/");
   #elif defined(__WXPM__)
@@ -267,92 +276,14 @@ wxString wxFileConfig::GetGlobalDir()
     if (rc == 0)
     {
         drive = aulSysInfo[QSV_BOOT_DRIVE - 1];
-        switch(drive)
-        {
-           case 1:
-              strDir = "A:\\OS2\\";
-              break;
-           case 2:
-              strDir = "B:\\OS2\\";
-              break;
-           case 3:
-              strDir = "C:\\OS2\\";
-              break;
-           case 4:
-              strDir = "D:\\OS2\\";
-              break;
-           case 5:
-              strDir = "E:\\OS2\\";
-              break;
-           case 6:
-              strDir = "F:\\OS2\\";
-              break;
-           case 7:
-              strDir = "G:\\OS2\\";
-              break;
-           case 8:
-              strDir = "H:\\OS2\\";
-              break;
-           case 9:
-              strDir = "I:\\OS2\\";
-              break;
-           case 10:
-              strDir = "J:\\OS2\\";
-              break;
-           case 11:
-              strDir = "K:\\OS2\\";
-              break;
-           case 12:
-              strDir = "L:\\OS2\\";
-              break;
-           case 13:
-              strDir = "M:\\OS2\\";
-              break;
-           case 14:
-              strDir = "N:\\OS2\\";
-              break;
-           case 15:
-              strDir = "O:\\OS2\\";
-              break;
-           case 16:
-              strDir = "P:\\OS2\\";
-              break;
-           case 17:
-              strDir = "Q:\\OS2\\";
-              break;
-           case 18:
-              strDir = "R:\\OS2\\";
-              break;
-           case 19:
-              strDir = "S:\\OS2\\";
-              break;
-           case 20:
-              strDir = "T:\\OS2\\";
-              break;
-           case 21:
-              strDir = "U:\\OS2\\";
-              break;
-           case 22:
-              strDir = "V:\\OS2\\";
-              break;
-           case 23:
-              strDir = "W:\\OS2\\";
-              break;
-           case 24:
-              strDir = "X:\\OS2\\";
-              break;
-           case 25:
-              strDir = "Y:\\OS2\\";
-              break;
-           case 26:
-              strDir = "Z:\\OS2\\";
-              break;
-        }
+        strDir.Printf(wxT("%c:\\OS2\\"), 'A'+drive-1);
     }
   #elif defined(__WXSTUBS__)
     wxASSERT_MSG( FALSE, wxT("TODO") ) ;
-  #elif defined(__WXMAC__)
-       strDir = wxMacFindFolder(  (short) kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder ) ;
+  #elif defined(__DOS__)
+    // There's no such thing as global cfg dir in MS-DOS, let's return
+    // current directory (FIXME_MGL?)
+    return wxT(".\\");
   #else // Windows
     wxChar szWinDir[MAX_PATH];
     ::GetWindowsDirectory(szWinDir, MAX_PATH);
@@ -368,20 +299,20 @@ wxString wxFileConfig::GetLocalDir()
 {
   wxString strDir;
 
-#ifndef __WXMAC__
+#if defined(__WXMAC__) || defined(__DOS__)
+  // no local dir concept on Mac OS 9 or MS-DOS
+  return GetGlobalDir() ;
+#else
   wxGetHomeDir(&strDir);
 
-#ifdef  __UNIX__
-#ifdef __VMS
-   if (strDir.Last() != wxT(']'))
-#endif
-   if (strDir.Last() != wxT('/')) strDir << wxT('/');
-#else
+#  ifdef  __UNIX__
+#  ifdef __VMS
+  if (strDir.Last() != wxT(']'))
+#  endif
+      if (strDir.Last() != wxT('/')) strDir << wxT('/');
+#  else
   if (strDir.Last() != wxT('\\')) strDir << wxT('\\');
-#endif
-#else
-       // no local dir concept on mac
-       return GetGlobalDir() ;
+#  endif
 #endif
 
   return strDir;
@@ -393,10 +324,10 @@ wxString wxFileConfig::GetGlobalFileName(const wxChar *szFile)
   str << szFile;
 
   if ( wxStrchr(szFile, wxT('.')) == NULL )
-  #ifdef  __UNIX__
-    str << wxT(".conf");
-  #elif defined( __WXMAC__ )
+  #if defined( __WXMAC__ )
      str << " Preferences";
+  #elif defined( __UNIX__ )
+    str << wxT(".conf");
   #else   // Windows
     str << wxT(".ini");
   #endif  // UNIX/Win
@@ -409,23 +340,22 @@ wxString wxFileConfig::GetLocalFileName(const wxChar *szFile)
 #ifdef __VMS__ // On VMS I saw the problem that the home directory was appended
    // twice for the configuration file. Does that also happen for other
    // platforms?
-   wxString str = wxT( '.' ); 
+   wxString str = wxT( '.' );
 #else
    wxString str = GetLocalDir();
 #endif
-   
-  #if defined( __UNIX__ ) && !defined( __VMS )
+
+  #if defined( __UNIX__ ) && !defined( __VMS ) && !defined( __WXMAC__ )
     str << wxT('.');
   #endif
 
   str << szFile;
 
-  #ifdef __WXMSW__
+  #if defined(__WINDOWS__) || defined(__DOS__)
     if ( wxStrchr(szFile, wxT('.')) == NULL )
       str << wxT(".ini");
   #endif
 
-
   #ifdef __WXMAC__
      str << " Preferences";
   #endif
@@ -524,6 +454,68 @@ wxFileConfig::wxFileConfig(const wxString& appName, const wxString& vendorName,
   Init();
 }
 
+#if wxUSE_STREAMS
+
+wxFileConfig::wxFileConfig(wxInputStream &inStream)
+{
+    // always local_file when this constructor is called (?)
+    SetStyle(GetStyle() | wxCONFIG_USE_LOCAL_FILE);
+
+    m_pCurrentGroup =
+    m_pRootGroup    = new wxFileConfigGroup(NULL, "", this);
+
+    m_linesHead =
+    m_linesTail = NULL;
+
+    // translate everything to the current (platform-dependent) line
+    // termination character
+    wxString strTrans;
+    {
+        wxString strTmp;
+
+        char buf[1024];
+        while ( !inStream.Read(buf, WXSIZEOF(buf)).Eof() )
+            strTmp.append(wxConvertMB2WX(buf), inStream.LastRead());
+
+        strTmp.append(wxConvertMB2WX(buf), inStream.LastRead());
+
+        strTrans = wxTextBuffer::Translate(strTmp);
+    }
+
+    wxMemoryText memText;
+
+    // Now we can add the text to the memory text. To do this we extract line
+    // by line from the translated string, until we've reached the end.
+    //
+    // VZ: all this is horribly inefficient, we should do the translation on
+    //     the fly in one pass saving both memory and time (TODO)
+
+    const wxChar *pEOL = wxTextBuffer::GetEOL(wxTextBuffer::typeDefault);
+    const size_t EOLLen = wxStrlen(pEOL);
+
+    int posLineStart = strTrans.Find(pEOL);
+    while ( posLineStart != -1 )
+    {
+        wxString line(strTrans.Left(posLineStart));
+
+        memText.AddLine(line);
+
+        strTrans = strTrans.Mid(posLineStart + EOLLen);
+
+        posLineStart = strTrans.Find(pEOL);
+    }
+
+    // also add whatever we have left in the translated string.
+    memText.AddLine(strTrans);
+
+    // Finally we can parse it all.
+    Parse(memText, TRUE /* local */);
+
+    SetRootPath();
+}
+
+#endif // wxUSE_STREAMS
+
 void wxFileConfig::CleanUp()
 {
   delete m_pRootGroup;
@@ -547,15 +539,15 @@ wxFileConfig::~wxFileConfig()
 // parse a config file
 // ----------------------------------------------------------------------------
 
-void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
+void wxFileConfig::Parse(wxTextBuffer& buffer, bool bLocal)
 {
   const wxChar *pStart;
   const wxChar *pEnd;
   wxString strLine;
 
-  size_t nLineCount = file.GetLineCount();
+  size_t nLineCount = buffer.GetLineCount();
   for ( size_t n = 0; n < nLineCount; n++ ) {
-    strLine = file[n];
+    strLine = buffer[n];
 
     // add the line to linked list
     if ( bLocal )
@@ -586,7 +578,7 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
 
       if ( *pEnd != wxT(']') ) {
         wxLogError(_("file '%s': unexpected character %c at line %d."),
-                   file.GetName(), *pEnd, n + 1);
+                   buffer.GetName(), *pEnd, n + 1);
         continue; // skip this line
       }
 
@@ -618,7 +610,7 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
 
           default:
             wxLogWarning(_("file '%s', line %d: '%s' ignored after group header."),
-                         file.GetName(), n + 1, pEnd);
+                         buffer.GetName(), n + 1, pEnd);
             bCont = FALSE;
         }
       }
@@ -647,7 +639,7 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
 
       if ( *pEnd++ != wxT('=') ) {
         wxLogError(_("file '%s', line %d: '=' expected."),
-                   file.GetName(), n + 1);
+                   buffer.GetName(), n + 1);
       }
       else {
         wxFileConfigEntry *pEntry = m_pCurrentGroup->FindEntry(strKey);
@@ -663,7 +655,7 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
           if ( bLocal && pEntry->IsImmutable() ) {
             // immutable keys can't be changed by user
             wxLogWarning(_("file '%s', line %d: value for immutable key '%s' ignored."),
-                         file.GetName(), n + 1, strKey.c_str());
+                         buffer.GetName(), n + 1, strKey.c_str());
             continue;
           }
           // the condition below catches the cases (a) and (b) but not (c):
@@ -673,7 +665,7 @@ void wxFileConfig::Parse(wxTextFile& file, 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."),
-                         file.GetName(), n + 1, strKey.c_str(), pEntry->Line());
+                         buffer.GetName(), n + 1, strKey.c_str(), pEntry->Line());
 
             if ( bLocal )
               pEntry->SetLine(m_linesTail);
@@ -684,7 +676,11 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
         while ( wxIsspace(*pEnd) )
           pEnd++;
 
-        pEntry->SetValue(FilterInValue(pEnd), FALSE /* read from file */);
+        wxString value = pEnd;
+        if ( !(GetStyle() & wxCONFIG_USE_NO_ESCAPE_CHARACTERS) )
+            value = FilterInValue(value);
+
+        pEntry->SetValue(value, FALSE);
       }
     }
   }
@@ -829,8 +825,7 @@ bool wxFileConfig::HasEntry(const wxString& strName) const
 // read/write values
 // ----------------------------------------------------------------------------
 
-bool wxFileConfig::Read(const wxString& key,
-                        wxString* pStr) const
+bool wxFileConfig::DoReadString(const wxString& key, wxString* pStr) const
 {
   wxConfigPathChanger path(this, key);
 
@@ -839,44 +834,22 @@ bool wxFileConfig::Read(const wxString& key,
     return FALSE;
   }
 
-  *pStr = ExpandEnvVars(pEntry->Value());
-  return TRUE;
-}
-
-bool wxFileConfig::Read(const wxString& key,
-                        wxString* pStr, const wxString& defVal) const
-{
-  wxConfigPathChanger path(this, key);
-
-  wxFileConfigEntry *pEntry = m_pCurrentGroup->FindEntry(path.Name());
-  bool ok;
-  if (pEntry == NULL) {
-    if( IsRecordingDefaults() )
-      ((wxFileConfig *)this)->Write(key,defVal);
-    *pStr = ExpandEnvVars(defVal);
-    ok = FALSE;
-  }
-  else {
-    *pStr = ExpandEnvVars(pEntry->Value());
-    ok = TRUE;
-  }
+  *pStr = pEntry->Value();
 
-  return ok;
+  return TRUE;
 }
 
-bool wxFileConfig::Read(const wxString& key, long *pl) const
+bool wxFileConfig::DoReadLong(const wxString& key, long *pl) const
 {
   wxString str;
   if ( !Read(key, & str) )
   {
     return FALSE;
   }
-
-  *pl = wxAtol(str);
-  return TRUE;
+  return str.ToLong(pl) ;
 }
 
-bool wxFileConfig::Write(const wxString& key, const wxString& szValue)
+bool wxFileConfig::DoWriteString(const wxString& key, const wxString& szValue)
 {
   wxConfigPathChanger path(this, key);
 
@@ -911,12 +884,9 @@ bool wxFileConfig::Write(const wxString& key, const wxString& szValue)
   return TRUE;
 }
 
-bool wxFileConfig::Write(const wxString& key, long lValue)
+bool wxFileConfig::DoWriteLong(const wxString& key, long lValue)
 {
-  // ltoa() is not ANSI :-(
-  wxString buf;
-  buf.Printf(wxT("%ld"), lValue);
-  return Write(key, buf);
+  return Write(key, wxString::Format(_T("%ld"), lValue));
 }
 
 bool wxFileConfig::Flush(bool /* bCurrentOnly */)
@@ -935,14 +905,24 @@ bool wxFileConfig::Flush(bool /* bCurrentOnly */)
 
   wxTempFile file(m_strLocalFile);
 
-  if ( !file.IsOpened() ) {
+  if ( !file.IsOpened() )
+  {
     wxLogError(_("can't open user configuration file."));
     return FALSE;
   }
 
   // write all strings to file
-  for ( wxFileConfigLineList *p = m_linesHead; p != NULL; p = p->Next() ) {
-    if ( !file.Write(p->Text() + wxTextFile::GetEOL()) ) {
+  for ( wxFileConfigLineList *p = m_linesHead; p != NULL; p = p->Next() )
+  {
+    wxString line = p->Text();
+    line += wxTextFile::GetEOL();
+#if wxUSE_UNICODE
+    wxCharBuffer buf = wxConvLocal.cWX2MB( line );
+    if ( !file.Write( (const char*)buf, strlen( (const char*) buf ) ) )
+#else
+    if ( !file.Write( line.c_str(), line.Len() ) )
+#endif
+    {
       wxLogError(_("can't write user configuration file."));
       return FALSE;
     }
@@ -950,11 +930,11 @@ bool wxFileConfig::Flush(bool /* bCurrentOnly */)
 
   bool ret = file.Commit();
 
-#if defined(__WXMAC__) && !defined(__UNIX__)
+#if defined(__WXMAC__)
   if ( ret )
   {
        FSSpec spec ;
-       
+
        wxMacFilename2FSSpec( m_strLocalFile , &spec ) ;
        FInfo finfo ;
        if ( FSpGetFInfo( &spec , &finfo ) == noErr )
@@ -964,7 +944,7 @@ bool wxFileConfig::Flush(bool /* bCurrentOnly */)
                FSpSetFInfo( &spec , &finfo ) ;
        }
   }
-#endif // __WXMAC__ && !__UNIX__
+#endif // __WXMAC__
 
 #ifdef __UNIX__
   // restore the old umask if we changed it
@@ -1601,9 +1581,16 @@ void wxFileConfigEntry::SetValue(const wxString& strValue, bool bUser)
   m_strValue = strValue;
 
   if ( bUser ) {
-    wxString strVal = FilterOutValue(strValue);
+    wxString strValFiltered;
+    if ( Group()->Config()->GetStyle() & wxCONFIG_USE_NO_ESCAPE_CHARACTERS ) {
+        strValFiltered = strValue;
+    }
+    else {
+        strValFiltered = FilterOutValue(strValue);
+    }
+
     wxString strLine;
-    strLine << FilterOutEntryName(m_strName) << wxT('=') << strVal;
+    strLine << FilterOutEntryName(m_strName) << wxT('=') << strValFiltered;
 
     if ( m_pLine != NULL ) {
       // entry was read from the local config file, just modify the line