]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/iniconf.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/iniconf.cpp
3 // Purpose: implementation of wxIniConfig class
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
19 // Doesn't yet compile in Unicode mode
21 #if wxUSE_CONFIG && !wxUSE_UNICODE
24 #include "wx/dynarray.h"
25 #include "wx/string.h"
33 #include "wx/config.h"
36 #include "wx/msw/iniconf.h"
38 // _WINDOWS_ is defined when windows.h is included,
39 // __WXMSW__ is defined for MS Windows compilation
40 #if defined(__WXMSW__) && !defined(_WINDOWS_)
41 #include "wx/msw/wrapwin.h"
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 // we replace all path separators with this character
49 #define PATH_SEP_REPLACE '_'
51 // ============================================================================
53 // ============================================================================
55 // ----------------------------------------------------------------------------
57 // ----------------------------------------------------------------------------
59 wxIniConfig::wxIniConfig(const wxString
& strAppName
,
60 const wxString
& strVendor
,
61 const wxString
& localFilename
,
62 const wxString
& globalFilename
,
64 : wxConfigBase(strAppName
, strVendor
, localFilename
, globalFilename
, style
)
66 #if 0 // This is too complex for some compilers, e.g. BC++ 5.01
67 : wxConfigBase((strAppName
.empty() && wxTheApp
) ? wxTheApp
->GetAppName()
69 strVendor
.empty() ? (wxTheApp
? wxTheApp
->GetVendorName()
72 localFilename
, globalFilename
, style
)
75 if (strAppName
.empty() && wxTheApp
)
76 SetAppName(wxTheApp
->GetAppName());
77 if (strVendor
.empty() && wxTheApp
)
78 SetVendorName(wxTheApp
->GetVendorName());
80 m_strLocalFilename
= localFilename
;
81 if (m_strLocalFilename
.empty())
83 m_strLocalFilename
= GetAppName() + wxT(".ini");
86 // append the extension if none given and it's not an absolute file name
87 // (otherwise we assume that they know what they're doing)
88 if ( !wxIsPathSeparator(m_strLocalFilename
[0u]) &&
89 m_strLocalFilename
.Find(wxT('.')) == wxNOT_FOUND
)
91 m_strLocalFilename
<< wxT(".ini");
95 SetPath(wxEmptyString
);
98 wxIniConfig::~wxIniConfig()
102 // ----------------------------------------------------------------------------
104 // ----------------------------------------------------------------------------
106 void wxIniConfig::SetPath(const wxString
& strPath
)
108 wxArrayString aParts
;
110 if ( strPath
.empty() ) {
113 else if ( strPath
[0u] == wxCONFIG_PATH_SEPARATOR
) {
115 wxSplitPath(aParts
, strPath
);
118 // relative path, combine with current one
119 wxString strFullPath
= GetPath();
120 strFullPath
<< wxCONFIG_PATH_SEPARATOR
<< strPath
;
121 wxSplitPath(aParts
, strFullPath
);
124 size_t nPartsCount
= aParts
.Count();
126 if ( nPartsCount
== 0 ) {
128 m_strGroup
= PATH_SEP_REPLACE
;
132 m_strGroup
= aParts
[0u];
133 for ( size_t nPart
= 1; nPart
< nPartsCount
; nPart
++ ) {
135 m_strPath
<< PATH_SEP_REPLACE
;
136 m_strPath
<< aParts
[nPart
];
140 // other functions assume that all this is true, i.e. there are no trailing
141 // underscores at the end except if the group is the root one
142 wxASSERT( (m_strPath
.empty() || m_strPath
.Last() != PATH_SEP_REPLACE
) &&
143 (m_strGroup
== wxString(PATH_SEP_REPLACE
) ||
144 m_strGroup
.Last() != PATH_SEP_REPLACE
) );
147 const wxString
& wxIniConfig::GetPath() const
149 static wxString s_str
;
151 // always return abs path
152 s_str
= wxCONFIG_PATH_SEPARATOR
;
154 if ( m_strGroup
== wxString(PATH_SEP_REPLACE
) ) {
155 // we're at the root level, nothing to do
159 if ( !m_strPath
.empty() )
160 s_str
<< wxCONFIG_PATH_SEPARATOR
;
161 for ( const char *p
= m_strPath
; *p
!= '\0'; p
++ ) {
162 s_str
<< (*p
== PATH_SEP_REPLACE
? wxCONFIG_PATH_SEPARATOR
: *p
);
169 wxString
wxIniConfig::GetPrivateKeyName(const wxString
& szKey
) const
173 if ( !m_strPath
.empty() )
174 strKey
<< m_strPath
<< PATH_SEP_REPLACE
;
181 wxString
wxIniConfig::GetKeyName(const wxString
& szKey
) const
185 if ( m_strGroup
!= wxString(PATH_SEP_REPLACE
) )
186 strKey
<< m_strGroup
<< PATH_SEP_REPLACE
;
187 if ( !m_strPath
.empty() )
188 strKey
<< m_strPath
<< PATH_SEP_REPLACE
;
195 // ----------------------------------------------------------------------------
197 // ----------------------------------------------------------------------------
200 bool wxIniConfig::GetFirstGroup(wxString
& WXUNUSED(str
), long& WXUNUSED(lIndex
)) const
202 wxFAIL_MSG("not implemented");
207 bool wxIniConfig::GetNextGroup (wxString
& WXUNUSED(str
), long& WXUNUSED(lIndex
)) const
209 wxFAIL_MSG("not implemented");
214 bool wxIniConfig::GetFirstEntry(wxString
& WXUNUSED(str
), long& WXUNUSED(lIndex
)) const
216 wxFAIL_MSG("not implemented");
221 bool wxIniConfig::GetNextEntry (wxString
& WXUNUSED(str
), long& WXUNUSED(lIndex
)) const
223 wxFAIL_MSG("not implemented");
228 // ----------------------------------------------------------------------------
230 // ----------------------------------------------------------------------------
233 size_t wxIniConfig::GetNumberOfEntries(bool WXUNUSED(bRecursive
)) const
235 wxFAIL_MSG("not implemented");
240 size_t wxIniConfig::GetNumberOfGroups(bool WXUNUSED(bRecursive
)) const
242 wxFAIL_MSG("not implemented");
247 bool wxIniConfig::HasGroup(const wxString
& WXUNUSED(strName
)) const
249 wxFAIL_MSG("not implemented");
254 bool wxIniConfig::HasEntry(const wxString
& WXUNUSED(strName
)) const
256 wxFAIL_MSG("not implemented");
261 // is current group empty?
262 bool wxIniConfig::IsEmpty() const
266 GetPrivateProfileString(m_strGroup
, NULL
, "",
267 szBuf
, WXSIZEOF(szBuf
), m_strLocalFilename
);
268 if ( !::IsEmpty(szBuf
) )
271 GetProfileString(m_strGroup
, NULL
, "", szBuf
, WXSIZEOF(szBuf
));
272 if ( !::IsEmpty(szBuf
) )
278 // ----------------------------------------------------------------------------
280 // ----------------------------------------------------------------------------
282 bool wxIniConfig::DoReadString(const wxString
& szKey
, wxString
*pstr
) const
284 wxConfigPathChanger
path(this, szKey
);
285 wxString strKey
= GetPrivateKeyName(path
.Name());
287 char szBuf
[1024]; // @@ should dynamically allocate memory...
289 // first look in the private INI file
291 // NB: the lpDefault param to GetPrivateProfileString can't be NULL
292 GetPrivateProfileString(m_strGroup
, strKey
, "",
293 szBuf
, WXSIZEOF(szBuf
), m_strLocalFilename
);
294 if ( ::IsEmpty(szBuf
) ) {
295 // now look in win.ini
296 wxString strKey
= GetKeyName(path
.Name());
297 GetProfileString(m_strGroup
, strKey
, "", szBuf
, WXSIZEOF(szBuf
));
300 if ( ::IsEmpty(szBuf
) )
307 bool wxIniConfig::DoReadLong(const wxString
& szKey
, long *pl
) const
309 wxConfigPathChanger
path(this, szKey
);
310 wxString strKey
= GetPrivateKeyName(path
.Name());
312 // hack: we have no mean to know if it really found the default value or
313 // didn't find anything, so we call it twice
315 static const int nMagic
= 17; // 17 is some "rare" number
316 static const int nMagic2
= 28; // arbitrary number != nMagic
317 long lVal
= GetPrivateProfileInt(m_strGroup
, strKey
, nMagic
, m_strLocalFilename
);
318 if ( lVal
!= nMagic
) {
319 // the value was read from the file
324 // is it really nMagic?
325 lVal
= GetPrivateProfileInt(m_strGroup
, strKey
, nMagic2
, m_strLocalFilename
);
326 if ( lVal
!= nMagic2
) {
327 // the nMagic it returned was indeed read from the file
332 // CS : I have no idea why they should look up in win.ini
333 // and if at all they have to do the same procedure using the two magic numbers
334 // otherwise it always returns true, even if the key was not there at all
336 // no, it was just returning the default value, so now look in win.ini
337 *pl
= GetProfileInt(GetVendorName(), GetKeyName(szKey
), *pl
);
344 bool wxIniConfig::DoWriteString(const wxString
& szKey
, const wxString
& szValue
)
346 wxConfigPathChanger
path(this, szKey
);
347 wxString strKey
= GetPrivateKeyName(path
.Name());
349 bool bOk
= WritePrivateProfileString(m_strGroup
, strKey
,
350 szValue
, m_strLocalFilename
) != 0;
353 wxLogLastError(wxT("WritePrivateProfileString"));
358 bool wxIniConfig::DoWriteLong(const wxString
& szKey
, long lValue
)
360 // ltoa() is not ANSI :-(
361 char szBuf
[40]; // should be good for sizeof(long) <= 16 (128 bits)
362 sprintf(szBuf
, "%ld", lValue
);
364 return Write(szKey
, szBuf
);
367 bool wxIniConfig::Flush(bool /* bCurrentOnly */)
369 // this is just the way it works
370 return WritePrivateProfileString(NULL
, NULL
, NULL
, m_strLocalFilename
) != 0;
373 // ----------------------------------------------------------------------------
375 // ----------------------------------------------------------------------------
377 bool wxIniConfig::DeleteEntry(const wxString
& szKey
, bool bGroupIfEmptyAlso
)
379 // passing NULL as value to WritePrivateProfileString deletes the key
380 wxConfigPathChanger
path(this, szKey
);
381 wxString strKey
= GetPrivateKeyName(path
.Name());
383 if (WritePrivateProfileString(m_strGroup
, strKey
,
384 (const char*) NULL
, m_strLocalFilename
) == 0)
387 if ( !bGroupIfEmptyAlso
|| !IsEmpty() )
390 // delete the current group too
391 bool bOk
= WritePrivateProfileString(m_strGroup
, NULL
,
392 NULL
, m_strLocalFilename
) != 0;
395 wxLogLastError(wxT("WritePrivateProfileString"));
400 bool wxIniConfig::DeleteGroup(const wxString
& szKey
)
402 wxConfigPathChanger
path(this, szKey
);
404 // passing NULL as section name to WritePrivateProfileString deletes the
405 // whole section according to the docs
406 bool bOk
= WritePrivateProfileString(path
.Name(), NULL
,
407 NULL
, m_strLocalFilename
) != 0;
410 wxLogLastError(wxT("WritePrivateProfileString"));
419 bool wxIniConfig::DeleteAll()
421 // first delete our group in win.ini
422 WriteProfileString(GetVendorName(), NULL
, NULL
);
424 // then delete our own ini file
425 char szBuf
[MAX_PATH
];
426 size_t nRc
= GetWindowsDirectory(szBuf
, WXSIZEOF(szBuf
));
429 wxLogLastError(wxT("GetWindowsDirectory"));
431 else if ( nRc
> WXSIZEOF(szBuf
) )
433 wxFAIL_MSG(wxT("buffer is too small for Windows directory."));
436 wxString strFile
= szBuf
;
437 strFile
<< '\\' << m_strLocalFilename
;
439 if ( wxFile::Exists(strFile
) && !wxRemoveFile(strFile
) ) {
440 wxLogSysError(_("Can't delete the INI file '%s'"), strFile
.c_str());
447 bool wxIniConfig::RenameEntry(const wxString
& WXUNUSED(oldName
),
448 const wxString
& WXUNUSED(newName
))
454 bool wxIniConfig::RenameGroup(const wxString
& WXUNUSED(oldName
),
455 const wxString
& WXUNUSED(newName
))
462 // wxUSE_CONFIG && wxUSE_UNICODE