#include "wx/fileconf.h"
#include "wx/filefn.h"
+#include "wx/stdpaths.h"
+
#if defined(__WXMAC__)
#include "wx/mac/private.h" // includes mac headers
- #include "wx/filename.h" // for MacSetTypeAndCreator
#endif
#if defined(__WXMSW__)
// ----------------------------------------------------------------------------
// static functions
// ----------------------------------------------------------------------------
-wxString wxFileConfig::GetGlobalDir()
-{
- wxString strDir;
-#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(__OS2__)
- ULONG aulSysInfo[QSV_MAX] = {0};
- UINT drive;
- APIRET rc;
-
- rc = DosQuerySysInfo( 1L, QSV_MAX, (PVOID)aulSysInfo, sizeof(ULONG)*QSV_MAX);
- if (rc == 0)
+// this function modifies in place the given wxFileName object if it doesn't
+// already have an extension
+//
+// note that it's slightly misnamed under Mac as there it doesn't add an
+// extension but modifies the file name instead, so you shouldn't suppose that
+// fn.HasExt() is true after it returns
+static void AddConfFileExtIfNeeded(wxFileName& fn)
+{
+ if ( !fn.HasExt() )
{
- drive = aulSysInfo[QSV_BOOT_DRIVE - 1];
- strDir.Printf(wxT("%c:\\OS2\\"), 'A'+drive-1);
+#if defined( __WXMAC__ )
+ fn.SetName(fn.GetName() + wxT(" Preferences"));
+#elif defined( __UNIX__ )
+ fn.SetExt(wxT(".conf"));
+#else // Windows
+ fn.SetExt(wxT(".ini"));
+#endif // UNIX/Win
}
-#elif defined(__WXSTUBS__)
- 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?)
- strDir = wxT(".\\");
-#elif defined(__WXWINCE__)
- strDir = wxT("\\Windows\\");
-#else // Windows
-
- wxChar szWinDir[MAX_PATH];
- ::GetWindowsDirectory(szWinDir, MAX_PATH);
-
- strDir = szWinDir;
- strDir << wxT('\\');
-#endif // Unix/Windows
-
- return strDir;
}
-wxString wxFileConfig::GetLocalDir()
+wxString wxFileConfig::GetGlobalDir()
{
- wxString strDir;
-
-#if defined(__WXMAC__) || defined(__DOS__)
- // no local dir concept on Mac OS 9 or MS-DOS
- strDir << GetGlobalDir() ;
-#else
- wxGetHomeDir(&strDir);
-
- #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;
+ return wxStandardPaths::Get().GetConfigDir();
}
-wxString wxFileConfig::GetGlobalFileName(const wxString& file)
+wxString wxFileConfig::GetLocalDir(int style)
{
- wxString str = GetGlobalDir();
- str << file;
+ wxUnusedVar(style);
- if ( wxStrchr(file, wxT('.')) == NULL )
-#if defined( __WXMAC__ )
- str << wxT(" Preferences") ;
-#elif defined( __UNIX__ )
- str << wxT(".conf");
-#else // Windows
- str << wxT(".ini");
-#endif // UNIX/Win
+ wxStandardPathsBase& stdp = wxStandardPaths::Get();
- return str;
+ // it so happens that user data directory is a subdirectory of user config
+ // directory on all supported platforms, which explains why we use it here
+ return style & wxCONFIG_USE_SUBDIR ? stdp.GetUserDataDir()
+ : stdp.GetUserConfigDir();
}
-wxString wxFileConfig::GetLocalFileName(const wxString& file)
+wxFileName wxFileConfig::GetGlobalFile(const wxString& 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( '.' );
-#else
- wxString str = GetLocalDir();
-#endif
+ wxFileName fn(GetGlobalDir(), szFile);
-#if defined( __UNIX__ ) && !defined( __VMS ) && !defined( __WXMAC__ )
- str << wxT('.');
-#endif
+ AddConfFileExtIfNeeded(fn);
- str << file;
+ return fn;
+}
-#if defined(__WINDOWS__) || defined(__DOS__)
- if ( wxStrchr(file, wxT('.')) == NULL )
- str << wxT(".ini");
-#endif
+wxFileName wxFileConfig::GetLocalFile(const wxString& szFile, int style)
+{
+ wxFileName fn(GetLocalDir(style), szFile);
-#ifdef __WXMAC__
- str << wxT(" Preferences") ;
-#endif
+#ifdef __UNIX__
+ if ( !(style & wxCONFIG_USE_SUBDIR) )
+ {
+ // dot-files under Unix start with, well, a dot (but OTOH they usually
+ // don't have any specific extension)
+ fn.SetName(wxT('.') + fn.GetName());
+ }
+ else // we do append ".conf" extension to config files in subdirectories
+#endif // __UNIX__
+ {
+ AddConfFileExtIfNeeded(fn);
+ }
- return str;
+ return fn;
}
// ----------------------------------------------------------------------------
// ctor
// ----------------------------------------------------------------------------
+IMPLEMENT_ABSTRACT_CLASS(wxFileConfig, wxConfigBase)
void wxFileConfig::Init()
{
// It's not an error if (one of the) file(s) doesn't exist.
// parse the global file
- if ( !m_strGlobalFile.empty() && wxFile::Exists(m_strGlobalFile) )
+ if ( m_fnGlobalFile.IsOk() && m_fnGlobalFile.FileExists() )
{
- wxTextFile fileGlobal(m_strGlobalFile);
+ wxTextFile fileGlobal(m_fnGlobalFile.GetFullPath());
if ( fileGlobal.Open(*m_conv/*ignored in ANSI build*/) )
{
}
else
{
- wxLogWarning(_("can't open global configuration file '%s'."), m_strGlobalFile.c_str());
+ wxLogWarning(_("can't open global configuration file '%s'."), m_fnGlobalFile.GetFullPath().c_str());
}
}
// parse the local file
- if ( !m_strLocalFile.empty() && wxFile::Exists(m_strLocalFile) )
+ if ( m_fnLocalFile.IsOk() && m_fnLocalFile.FileExists() )
{
- wxTextFile fileLocal(m_strLocalFile);
+ wxTextFile fileLocal(m_fnLocalFile.GetFullPath());
if ( fileLocal.Open(*m_conv/*ignored in ANSI build*/) )
{
Parse(fileLocal, true /* local */);
}
else
{
- wxLogWarning(_("can't open user configuration file '%s'."), m_strLocalFile.c_str() );
+ wxLogWarning(_("can't open user configuration file '%s'."), m_fnLocalFile.GetFullPath().c_str() );
}
}
: wxConfigBase(::GetAppName(appName), vendorName,
strLocal, strGlobal,
style),
- m_strLocalFile(strLocal), m_strGlobalFile(strGlobal),
+ m_fnLocalFile(strLocal),
+ m_fnGlobalFile(strGlobal),
m_conv(conv.Clone())
{
// 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_fnLocalFile.IsOk() && (style & wxCONFIG_USE_LOCAL_FILE) )
+ m_fnLocalFile = GetLocalFile(GetAppName(), style);
- if ( m_strGlobalFile.empty() && (style & wxCONFIG_USE_GLOBAL_FILE) )
- m_strGlobalFile = GetGlobalFileName(GetAppName());
+ if ( !m_fnGlobalFile.IsOk() && (style & wxCONFIG_USE_GLOBAL_FILE) )
+ m_fnGlobalFile = GetGlobalFile(GetAppName());
// Check if styles are not supplied, but filenames are, in which case
// add the correct styles.
- if ( !m_strLocalFile.empty() )
+ if ( m_fnLocalFile.IsOk() )
SetStyle(GetStyle() | wxCONFIG_USE_LOCAL_FILE);
- if ( !m_strGlobalFile.empty() )
+ if ( m_fnGlobalFile.IsOk() )
SetStyle(GetStyle() | wxCONFIG_USE_GLOBAL_FILE);
// if the path is not absolute, prepend the standard directory to it
- // UNLESS wxCONFIG_USE_RELATIVE_PATH style is set
+ // unless explicitly asked not to
if ( !(style & wxCONFIG_USE_RELATIVE_PATH) )
{
- if ( !m_strLocalFile.empty() && !wxIsAbsolutePath(m_strLocalFile) )
- {
- const wxString strLocalOrig = m_strLocalFile;
- m_strLocalFile = GetLocalDir();
- m_strLocalFile << strLocalOrig;
- }
+ if ( m_fnLocalFile.IsOk() )
+ m_fnLocalFile.MakeAbsolute(GetLocalDir(style));
- if ( !m_strGlobalFile.empty() && !wxIsAbsolutePath(m_strGlobalFile) )
- {
- const wxString strGlobalOrig = m_strGlobalFile;
- m_strGlobalFile = GetGlobalDir();
- m_strGlobalFile << strGlobalOrig;
- }
+ if ( m_fnGlobalFile.IsOk() )
+ m_fnGlobalFile.MakeAbsolute(GetGlobalDir());
}
SetUmask(-1);
m_linesHead =
m_linesTail = NULL;
- // translate everything to the current (platform-dependent) line
- // termination character
- wxString strTrans;
+ // read the entire stream contents in memory
+ wxString str;
{
- wxString strTmp;
+ static const size_t chunkLen = 1024;
- char buf[1024];
+ wxMemoryBuffer buf(chunkLen);
do
{
- inStream.Read(buf, WXSIZEOF(buf)-1); // leave room for the NULL
+ inStream.Read(buf.GetAppendBuf(chunkLen), chunkLen);
+ buf.UngetAppendBuf(inStream.LastRead());
const wxStreamError err = inStream.GetLastError();
wxLogError(_("Error reading config options."));
break;
}
-
- // FIXME: this is broken because if we have part of multibyte
- // character in the buffer (and another part hasn't been
- // read yet) we're going to lose data because of conversion
- // errors
- buf[inStream.LastRead()] = '\0';
- strTmp += conv.cMB2WX(buf);
}
while ( !inStream.Eof() );
- strTrans = wxTextBuffer::Translate(strTmp);
+#if wxUSE_UNICODE
+ size_t len;
+ str = conv.cMB2WC((char *)buf.GetData(), buf.GetDataLen(), &len);
+ if ( !len && buf.GetDataLen() )
+ {
+ wxLogError(_("Failed to read config options."));
+ }
+#else // !wxUSE_UNICODE
+ // no need for conversion
+ str.assign((char *)buf.GetData(), buf.GetDataLen());
+#endif // wxUSE_UNICODE/!wxUSE_UNICODE
}
+
+ // translate everything to the current (platform-dependent) line
+ // termination character
+ str = wxTextBuffer::Translate(str);
+
wxMemoryText memText;
// Now we can add the text to the memory text. To do this we extract line
const wxChar *pEOL = wxTextBuffer::GetEOL(wxTextBuffer::typeDefault);
const size_t EOLLen = wxStrlen(pEOL);
- int posLineStart = strTrans.Find(pEOL);
+ int posLineStart = str.Find(pEOL);
while ( posLineStart != -1 )
{
- wxString line(strTrans.Left(posLineStart));
+ wxString line(str.Left(posLineStart));
memText.AddLine(line);
- strTrans = strTrans.Mid(posLineStart + EOLLen);
+ str = str.Mid(posLineStart + EOLLen);
- posLineStart = strTrans.Find(pEOL);
+ posLineStart = str.Find(pEOL);
}
// also add whatever we have left in the translated string.
- if ( !strTrans.empty() )
- memText.AddLine(strTrans);
+ if ( !str.empty() )
+ memText.AddLine(str);
// Finally we can parse it all.
Parse(memText, true /* local */);
bool wxFileConfig::Flush(bool /* bCurrentOnly */)
{
- if ( !IsDirty() || !m_strLocalFile )
+ if ( !IsDirty() || !m_fnLocalFile.GetFullPath() )
return true;
// set the umask if needed
wxCHANGE_UMASK(m_umask);
- wxTempFile file(m_strLocalFile);
+ wxTempFile file(m_fnLocalFile.GetFullPath());
if ( !file.IsOpened() )
{
ResetDirty();
#if defined(__WXMAC__)
- wxFileName(m_strLocalFile).MacSetTypeAndCreator('TEXT', 'ttxt');
+ m_fnLocalFile.MacSetTypeAndCreator('TEXT', 'ttxt');
#endif // __WXMAC__
return true;
{
CleanUp();
- if ( !m_strLocalFile.empty() )
+ if ( m_fnLocalFile.IsOk() )
{
- if ( wxFile::Exists(m_strLocalFile) && wxRemove(m_strLocalFile) == -1 )
+ if ( m_fnLocalFile.FileExists() && wxRemove(m_fnLocalFile.GetFullPath()) == -1 )
{
wxLogSysError(_("can't delete user configuration file '%s'"),
- m_strLocalFile.c_str());
+ m_fnLocalFile.GetFullPath().c_str());
return false;
}
}
str.c_str() );
wxLogTrace( FILECONF_TRACE_MASK,
_T(" head: %s"),
- ((m_linesHead) ? m_linesHead->Text().c_str() : wxEmptyString) );
+ ((m_linesHead) ? (const wxChar*)m_linesHead->Text().c_str()
+ : wxEmptyString) );
wxLogTrace( FILECONF_TRACE_MASK,
_T(" tail: %s"),
- ((m_linesTail) ? m_linesTail->Text().c_str() : wxEmptyString) );
+ ((m_linesTail) ? (const wxChar*)m_linesTail->Text().c_str()
+ : wxEmptyString) );
wxFileConfigLineList *pLine = new wxFileConfigLineList(str);
wxLogTrace( FILECONF_TRACE_MASK,
_T(" head: %s"),
- ((m_linesHead) ? m_linesHead->Text().c_str() : wxEmptyString) );
+ ((m_linesHead) ? (const wxChar*)m_linesHead->Text().c_str()
+ : wxEmptyString) );
wxLogTrace( FILECONF_TRACE_MASK,
_T(" tail: %s"),
- ((m_linesTail) ? m_linesTail->Text().c_str() : wxEmptyString) );
+ ((m_linesTail) ? (const wxChar*)m_linesTail->Text().c_str()
+ : wxEmptyString) );
return m_linesTail;
}
wxLogTrace( FILECONF_TRACE_MASK,
_T(" ** Inserting Line '%s' after '%s'"),
str.c_str(),
- ((pLine) ? pLine->Text().c_str() : wxEmptyString) );
+ ((pLine) ? (const wxChar*)pLine->Text().c_str()
+ : wxEmptyString) );
wxLogTrace( FILECONF_TRACE_MASK,
_T(" head: %s"),
- ((m_linesHead) ? m_linesHead->Text().c_str() : wxEmptyString) );
+ ((m_linesHead) ? (const wxChar*)m_linesHead->Text().c_str()
+ : wxEmptyString) );
wxLogTrace( FILECONF_TRACE_MASK,
_T(" tail: %s"),
- ((m_linesTail) ? m_linesTail->Text().c_str() : wxEmptyString) );
+ ((m_linesTail) ? (const wxChar*)m_linesTail->Text().c_str()
+ : wxEmptyString) );
if ( pLine == m_linesTail )
return LineListAppend(str);
wxLogTrace( FILECONF_TRACE_MASK,
_T(" head: %s"),
- ((m_linesHead) ? m_linesHead->Text().c_str() : wxEmptyString) );
+ ((m_linesHead) ? (const wxChar*)m_linesHead->Text().c_str()
+ : wxEmptyString) );
wxLogTrace( FILECONF_TRACE_MASK,
_T(" tail: %s"),
- ((m_linesTail) ? m_linesTail->Text().c_str() : wxEmptyString) );
+ ((m_linesTail) ? (const wxChar*)m_linesTail->Text().c_str()
+ : wxEmptyString) );
return pNewLine;
}
pLine->Text().c_str() );
wxLogTrace( FILECONF_TRACE_MASK,
_T(" head: %s"),
- ((m_linesHead) ? m_linesHead->Text().c_str() : wxEmptyString) );
+ ((m_linesHead) ? (const wxChar*)m_linesHead->Text().c_str()
+ : wxEmptyString) );
wxLogTrace( FILECONF_TRACE_MASK,
_T(" tail: %s"),
- ((m_linesTail) ? m_linesTail->Text().c_str() : wxEmptyString) );
+ ((m_linesTail) ? (const wxChar*)m_linesTail->Text().c_str()
+ : wxEmptyString) );
wxFileConfigLineList *pPrev = pLine->Prev(),
*pNext = pLine->Next();
wxLogTrace( FILECONF_TRACE_MASK,
_T(" head: %s"),
- ((m_linesHead) ? m_linesHead->Text().c_str() : wxEmptyString) );
+ ((m_linesHead) ? (const wxChar*)m_linesHead->Text().c_str()
+ : wxEmptyString) );
wxLogTrace( FILECONF_TRACE_MASK,
_T(" tail: %s"),
- ((m_linesTail) ? m_linesTail->Text().c_str() : wxEmptyString) );
+ ((m_linesTail) ? (const wxChar*)m_linesTail->Text().c_str()
+ : wxEmptyString) );
delete 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 ? (const wxChar*)m_pLine->Text().c_str()
+ : wxEmptyString );
// delete all entries...
size_t nCount = pGroup->m_aEntries.Count();
wxLogTrace( FILECONF_TRACE_MASK,
_T(" Removing from group '%s' : '%s'"),
Name().c_str(),
- ((m_pLine) ? m_pLine->Text().c_str() : wxEmptyString) );
+ ((m_pLine) ? (const wxChar*)m_pLine->Text().c_str()
+ : wxEmptyString) );
// notice that we may do this test inside the previous "if"
// because the last entry's line is surely !NULL
for ( size_t n = bQuoted ? 1 : 0; n < str.Len(); n++ ) {
if ( str[n] == wxT('\\') ) {
- switch ( str[++n] ) {
+ switch ( str[++n].GetValue() ) {
case wxT('n'):
strResult += wxT('\n');
break;
wxChar c;
for ( size_t n = 0; n < str.Len(); n++ ) {
- switch ( str[n] ) {
+ switch ( str[n].GetValue() ) {
case wxT('\n'):
c = wxT('n');
break;