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