#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
// "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
#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__)
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);
{
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;
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
#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
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;
// 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 )
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
}
default:
wxLogWarning(_("file '%s', line %d: '%s' ignored after group header."),
- file.GetName(), n + 1, pEnd);
+ buffer.GetName(), n + 1, pEnd);
bCont = FALSE;
}
}
if ( *pEnd++ != wxT('=') ) {
wxLogError(_("file '%s', line %d: '=' expected."),
- file.GetName(), n + 1);
+ buffer.GetName(), n + 1);
}
else {
wxFileConfigEntry *pEntry = m_pCurrentGroup->FindEntry(strKey);
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):
// 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);
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);
}
}
}
// 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);
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);
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 */)
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;
}
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 )
FSpSetFInfo( &spec , &finfo ) ;
}
}
-#endif // __WXMAC__ && !__UNIX__
+#endif // __WXMAC__
#ifdef __UNIX__
// restore the old umask if we changed it
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