]> git.saurik.com Git - wxWidgets.git/blame - src/msw/iniconf.cpp
fix memory leak (coverity checker CID 53)
[wxWidgets.git] / src / msw / iniconf.cpp
CommitLineData
02569ba8
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/msw/iniconf.cpp
3// Purpose: implementation of wxIniConfig class
4// Author: Vadim Zeitlin
9869734d 5// Modified by:
02569ba8
VZ
6// Created: 27.07.98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
65571936 9// Licence: wxWindows licence
02569ba8
VZ
10///////////////////////////////////////////////////////////////////////////////
11
a3b46648
UU
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
02569ba8 14
a3b46648
UU
15#ifdef __BORLANDC__
16#pragma hdrstop
17#endif
02569ba8
VZ
18
19#ifndef WX_PRECOMP
3096bd2f
VZ
20 #include "wx/string.h"
21 #include "wx/intl.h"
22 #include "wx/event.h"
23 #include "wx/app.h"
24 #include "wx/utils.h"
02569ba8
VZ
25#endif //WX_PRECOMP
26
f6bcfd97
BP
27// Doesn't yet compile in Unicode mode
28
29#if wxUSE_CONFIG && !wxUSE_UNICODE
30
3096bd2f
VZ
31#include "wx/dynarray.h"
32#include "wx/log.h"
33#include "wx/config.h"
999836aa 34#include "wx/file.h"
02569ba8 35
3096bd2f 36#include "wx/msw/iniconf.h"
02569ba8
VZ
37
38// _WINDOWS_ is defined when windows.h is included,
39// __WXMSW__ is defined for MS Windows compilation
40#if defined(__WXMSW__) && !defined(_WINDOWS_)
9ed0d735 41 #include "wx/msw/wrapwin.h"
02569ba8
VZ
42#endif //windows.h
43
44// ----------------------------------------------------------------------------
45// constants
46// ----------------------------------------------------------------------------
47
48// we replace all path separators with this character
49#define PATH_SEP_REPLACE '_'
50
51// ============================================================================
52// implementation
53// ============================================================================
54
55// ----------------------------------------------------------------------------
56// ctor & dtor
57// ----------------------------------------------------------------------------
58
9869734d
VZ
59wxIniConfig::wxIniConfig(const wxString& strAppName,
60 const wxString& strVendor,
61 const wxString& localFilename,
62 const wxString& globalFilename,
63 long style)
8f19c916
JS
64 : wxConfigBase(strAppName, strVendor, localFilename, globalFilename, style)
65
66#if 0 // This is too complex for some compilers, e.g. BC++ 5.01
67 : wxConfigBase((strAppName.IsEmpty() && wxTheApp) ? wxTheApp->GetAppName()
d2c7e39b 68 : strAppName,
8f19c916 69 strVendor.IsEmpty() ? (wxTheApp ? wxTheApp->GetVendorName()
d2c7e39b
JS
70 : strAppName)
71 : strVendor,
72 localFilename, globalFilename, style)
8f19c916 73#endif
02569ba8 74{
8f19c916
JS
75 if (strAppName.IsEmpty() && wxTheApp)
76 SetAppName(wxTheApp->GetAppName());
77 if (strVendor.IsEmpty() && wxTheApp)
78 SetVendorName(wxTheApp->GetVendorName());
79
18244936
JS
80 m_strLocalFilename = localFilename;
81 if (m_strLocalFilename.IsEmpty())
82 {
f6bcfd97 83 m_strLocalFilename = GetAppName() + wxT(".ini");
18244936
JS
84 }
85
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]) &&
f6bcfd97 89 m_strLocalFilename.Find(wxT('.')) == wxNOT_FOUND )
18244936 90 {
f6bcfd97 91 m_strLocalFilename << wxT(".ini");
18244936
JS
92 }
93
94 // set root path
fda7962d 95 SetPath(wxEmptyString);
02569ba8
VZ
96}
97
98wxIniConfig::~wxIniConfig()
99{
100}
101
102// ----------------------------------------------------------------------------
103// path management
104// ----------------------------------------------------------------------------
105
106void wxIniConfig::SetPath(const wxString& strPath)
107{
108 wxArrayString aParts;
109
110 if ( strPath.IsEmpty() ) {
111 // nothing
112 }
113 else if ( strPath[0u] == wxCONFIG_PATH_SEPARATOR ) {
114 // absolute path
115 wxSplitPath(aParts, strPath);
116 }
117 else {
118 // relative path, combine with current one
119 wxString strFullPath = GetPath();
120 strFullPath << wxCONFIG_PATH_SEPARATOR << strPath;
121 wxSplitPath(aParts, strFullPath);
122 }
123
c86f1403 124 size_t nPartsCount = aParts.Count();
02569ba8
VZ
125 m_strPath.Empty();
126 if ( nPartsCount == 0 ) {
127 // go to the root
128 m_strGroup = PATH_SEP_REPLACE;
129 }
130 else {
131 // translate
132 m_strGroup = aParts[0u];
c86f1403 133 for ( size_t nPart = 1; nPart < nPartsCount; nPart++ ) {
02569ba8
VZ
134 if ( nPart > 1 )
135 m_strPath << PATH_SEP_REPLACE;
136 m_strPath << aParts[nPart];
137 }
138 }
139
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.IsEmpty() || m_strPath.Last() != PATH_SEP_REPLACE) &&
62448488 143 (m_strGroup == wxString(PATH_SEP_REPLACE) ||
02569ba8
VZ
144 m_strGroup.Last() != PATH_SEP_REPLACE) );
145}
146
147const wxString& wxIniConfig::GetPath() const
148{
149 static wxString s_str;
150
151 // always return abs path
152 s_str = wxCONFIG_PATH_SEPARATOR;
153
ce3ed50d 154 if ( m_strGroup == wxString(PATH_SEP_REPLACE) ) {
02569ba8
VZ
155 // we're at the root level, nothing to do
156 }
157 else {
158 s_str << m_strGroup;
159 if ( !m_strPath.IsEmpty() )
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);
163 }
164 }
165
166 return s_str;
167}
168
18244936 169wxString wxIniConfig::GetPrivateKeyName(const wxString& szKey) const
02569ba8
VZ
170{
171 wxString strKey;
172
173 if ( !m_strPath.IsEmpty() )
174 strKey << m_strPath << PATH_SEP_REPLACE;
175
176 strKey << szKey;
177
178 return strKey;
179}
180
18244936 181wxString wxIniConfig::GetKeyName(const wxString& szKey) const
02569ba8
VZ
182{
183 wxString strKey;
184
62448488 185 if ( m_strGroup != wxString(PATH_SEP_REPLACE) )
02569ba8
VZ
186 strKey << m_strGroup << PATH_SEP_REPLACE;
187 if ( !m_strPath.IsEmpty() )
188 strKey << m_strPath << PATH_SEP_REPLACE;
189
190 strKey << szKey;
191
192 return strKey;
193}
194
195// ----------------------------------------------------------------------------
196// enumeration
197// ----------------------------------------------------------------------------
198
199// not implemented
2eb10e2a 200bool wxIniConfig::GetFirstGroup(wxString& WXUNUSED(str), long& WXUNUSED(lIndex)) const
02569ba8
VZ
201{
202 wxFAIL_MSG("not implemented");
203
59af881e 204 return false;
02569ba8
VZ
205}
206
2eb10e2a 207bool wxIniConfig::GetNextGroup (wxString& WXUNUSED(str), long& WXUNUSED(lIndex)) const
02569ba8
VZ
208{
209 wxFAIL_MSG("not implemented");
210
59af881e 211 return false;
02569ba8
VZ
212}
213
2eb10e2a 214bool wxIniConfig::GetFirstEntry(wxString& WXUNUSED(str), long& WXUNUSED(lIndex)) const
02569ba8
VZ
215{
216 wxFAIL_MSG("not implemented");
217
59af881e 218 return false;
02569ba8
VZ
219}
220
2eb10e2a 221bool wxIniConfig::GetNextEntry (wxString& WXUNUSED(str), long& WXUNUSED(lIndex)) const
02569ba8
VZ
222{
223 wxFAIL_MSG("not implemented");
224
59af881e 225 return false;
02569ba8
VZ
226}
227
228// ----------------------------------------------------------------------------
229// misc info
230// ----------------------------------------------------------------------------
231
232// not implemented
2eb10e2a 233size_t wxIniConfig::GetNumberOfEntries(bool WXUNUSED(bRecursive)) const
02569ba8
VZ
234{
235 wxFAIL_MSG("not implemented");
236
c86f1403 237 return (size_t)-1;
02569ba8
VZ
238}
239
2eb10e2a 240size_t wxIniConfig::GetNumberOfGroups(bool WXUNUSED(bRecursive)) const
02569ba8
VZ
241{
242 wxFAIL_MSG("not implemented");
243
c86f1403 244 return (size_t)-1;
02569ba8
VZ
245}
246
2eb10e2a 247bool wxIniConfig::HasGroup(const wxString& WXUNUSED(strName)) const
02569ba8
VZ
248{
249 wxFAIL_MSG("not implemented");
250
59af881e 251 return false;
02569ba8
VZ
252}
253
2eb10e2a 254bool wxIniConfig::HasEntry(const wxString& WXUNUSED(strName)) const
02569ba8
VZ
255{
256 wxFAIL_MSG("not implemented");
257
59af881e 258 return false;
02569ba8
VZ
259}
260
261// is current group empty?
262bool wxIniConfig::IsEmpty() const
263{
264 char szBuf[1024];
265
266 GetPrivateProfileString(m_strGroup, NULL, "",
18244936 267 szBuf, WXSIZEOF(szBuf), m_strLocalFilename);
02569ba8 268 if ( !::IsEmpty(szBuf) )
59af881e 269 return false;
02569ba8
VZ
270
271 GetProfileString(m_strGroup, NULL, "", szBuf, WXSIZEOF(szBuf));
272 if ( !::IsEmpty(szBuf) )
59af881e 273 return false;
02569ba8 274
59af881e 275 return true;
02569ba8
VZ
276}
277
278// ----------------------------------------------------------------------------
279// read/write
280// ----------------------------------------------------------------------------
281
2ba41305 282bool wxIniConfig::DoReadString(const wxString& szKey, wxString *pstr) const
02569ba8 283{
18244936 284 wxConfigPathChanger path(this, szKey);
02569ba8
VZ
285 wxString strKey = GetPrivateKeyName(path.Name());
286
287 char szBuf[1024]; // @@ should dynamically allocate memory...
288
289 // first look in the private INI file
290
291 // NB: the lpDefault param to GetPrivateProfileString can't be NULL
292 GetPrivateProfileString(m_strGroup, strKey, "",
18244936 293 szBuf, WXSIZEOF(szBuf), m_strLocalFilename);
02569ba8
VZ
294 if ( ::IsEmpty(szBuf) ) {
295 // now look in win.ini
296 wxString strKey = GetKeyName(path.Name());
297 GetProfileString(m_strGroup, strKey, "", szBuf, WXSIZEOF(szBuf));
298 }
299
0cb50c83 300 if ( ::IsEmpty(szBuf) )
59af881e 301 return false;
0cb50c83
VZ
302
303 *pstr = szBuf;
59af881e 304 return true;
02569ba8
VZ
305}
306
2ba41305 307bool wxIniConfig::DoReadLong(const wxString& szKey, long *pl) const
02569ba8 308{
18244936 309 wxConfigPathChanger path(this, szKey);
02569ba8
VZ
310 wxString strKey = GetPrivateKeyName(path.Name());
311
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
314
315 static const int nMagic = 17; // 17 is some "rare" number
316 static const int nMagic2 = 28; // arbitrary number != nMagic
18244936 317 long lVal = GetPrivateProfileInt(m_strGroup, strKey, nMagic, m_strLocalFilename);
02569ba8
VZ
318 if ( lVal != nMagic ) {
319 // the value was read from the file
320 *pl = lVal;
59af881e 321 return true;
02569ba8
VZ
322 }
323
324 // is it really nMagic?
18244936 325 lVal = GetPrivateProfileInt(m_strGroup, strKey, nMagic2, m_strLocalFilename);
519cb848 326 if ( lVal != nMagic2 ) {
02569ba8
VZ
327 // the nMagic it returned was indeed read from the file
328 *pl = lVal;
59af881e 329 return true;
02569ba8
VZ
330 }
331
519cb848
SC
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
335#if 0
02569ba8 336 // no, it was just returning the default value, so now look in win.ini
519cb848 337 *pl = GetProfileInt(GetVendorName(), GetKeyName(szKey), *pl);
02569ba8 338
59af881e 339 return true;
519cb848 340#endif
59af881e 341 return false ;
02569ba8
VZ
342}
343
2ba41305 344bool wxIniConfig::DoWriteString(const wxString& szKey, const wxString& szValue)
02569ba8 345{
18244936 346 wxConfigPathChanger path(this, szKey);
02569ba8
VZ
347 wxString strKey = GetPrivateKeyName(path.Name());
348
349 bool bOk = WritePrivateProfileString(m_strGroup, strKey,
18244936 350 szValue, m_strLocalFilename) != 0;
02569ba8
VZ
351
352 if ( !bOk )
f6bcfd97 353 wxLogLastError(wxT("WritePrivateProfileString"));
02569ba8
VZ
354
355 return bOk;
356}
357
2ba41305 358bool wxIniConfig::DoWriteLong(const wxString& szKey, long lValue)
02569ba8
VZ
359{
360 // ltoa() is not ANSI :-(
361 char szBuf[40]; // should be good for sizeof(long) <= 16 (128 bits)
362 sprintf(szBuf, "%ld", lValue);
363
364 return Write(szKey, szBuf);
365}
366
367bool wxIniConfig::Flush(bool /* bCurrentOnly */)
368{
369 // this is just the way it works
18244936 370 return WritePrivateProfileString(NULL, NULL, NULL, m_strLocalFilename) != 0;
02569ba8
VZ
371}
372
373// ----------------------------------------------------------------------------
374// delete
375// ----------------------------------------------------------------------------
376
1e6d9499 377bool wxIniConfig::DeleteEntry(const wxString& szKey, bool bGroupIfEmptyAlso)
02569ba8
VZ
378{
379 // passing NULL as value to WritePrivateProfileString deletes the key
2432b92d
JS
380 wxConfigPathChanger path(this, szKey);
381 wxString strKey = GetPrivateKeyName(path.Name());
382
ff1b5f81 383 if (WritePrivateProfileString(m_strGroup, strKey,
2432b92d 384 (const char*) NULL, m_strLocalFilename) == 0)
59af881e 385 return false;
2432b92d 386
02569ba8 387 if ( !bGroupIfEmptyAlso || !IsEmpty() )
59af881e 388 return true;
02569ba8
VZ
389
390 // delete the current group too
391 bool bOk = WritePrivateProfileString(m_strGroup, NULL,
18244936 392 NULL, m_strLocalFilename) != 0;
02569ba8
VZ
393
394 if ( !bOk )
f6bcfd97 395 wxLogLastError(wxT("WritePrivateProfileString"));
02569ba8
VZ
396
397 return bOk;
398}
399
1e6d9499 400bool wxIniConfig::DeleteGroup(const wxString& szKey)
02569ba8 401{
18244936 402 wxConfigPathChanger path(this, szKey);
02569ba8 403
9869734d 404 // passing NULL as section name to WritePrivateProfileString deletes the
02569ba8
VZ
405 // whole section according to the docs
406 bool bOk = WritePrivateProfileString(path.Name(), NULL,
18244936 407 NULL, m_strLocalFilename) != 0;
02569ba8
VZ
408
409 if ( !bOk )
f6bcfd97 410 wxLogLastError(wxT("WritePrivateProfileString"));
02569ba8
VZ
411
412 return bOk;
413}
414
1e6d9499
JS
415#ifndef MAX_PATH
416#define MAX_PATH 256
417#endif
418
02569ba8
VZ
419bool wxIniConfig::DeleteAll()
420{
421 // first delete our group in win.ini
18244936 422 WriteProfileString(GetVendorName(), NULL, NULL);
02569ba8
VZ
423
424 // then delete our own ini file
425 char szBuf[MAX_PATH];
c86f1403 426 size_t nRc = GetWindowsDirectory(szBuf, WXSIZEOF(szBuf));
02569ba8 427 if ( nRc == 0 )
a1665b22 428 {
f6bcfd97 429 wxLogLastError(wxT("GetWindowsDirectory"));
a1665b22 430 }
02569ba8 431 else if ( nRc > WXSIZEOF(szBuf) )
a1665b22 432 {
f6bcfd97 433 wxFAIL_MSG(wxT("buffer is too small for Windows directory."));
a1665b22 434 }
02569ba8
VZ
435
436 wxString strFile = szBuf;
18244936 437 strFile << '\\' << m_strLocalFilename;
02569ba8 438
cb820f80 439 if ( wxFile::Exists(strFile) && !wxRemoveFile(strFile) ) {
02569ba8 440 wxLogSysError(_("Can't delete the INI file '%s'"), strFile.c_str());
59af881e 441 return false;
02569ba8
VZ
442 }
443
59af881e 444 return true;
02569ba8 445}
574c0bbf 446
2eb10e2a
VZ
447bool wxIniConfig::RenameEntry(const wxString& WXUNUSED(oldName),
448 const wxString& WXUNUSED(newName))
574c0bbf
JS
449{
450 // Not implemented
59af881e 451 return false;
574c0bbf
JS
452}
453
2eb10e2a
VZ
454bool wxIniConfig::RenameGroup(const wxString& WXUNUSED(oldName),
455 const wxString& WXUNUSED(newName))
574c0bbf
JS
456{
457 // Not implemented
59af881e 458 return false;
574c0bbf 459}
f6bcfd97
BP
460
461#endif
462 // wxUSE_CONFIG && wxUSE_UNICODE