]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/iniconf.cpp
Back to previous call with -1 replacement.
[wxWidgets.git] / src / msw / iniconf.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/msw/iniconf.cpp
3// Purpose: implementation of wxIniConfig class
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 27.07.98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16 #pragma hdrstop
17#endif
18
19// Doesn't yet compile in Unicode mode
20
21#if wxUSE_CONFIG && !wxUSE_UNICODE
22
23#ifndef WX_PRECOMP
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"
32#endif //WX_PRECOMP
33
34#include "wx/config.h"
35#include "wx/file.h"
36
37#include "wx/msw/iniconf.h"
38
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
54wxIniConfig::wxIniConfig(const wxString& strAppName,
55 const wxString& strVendor,
56 const wxString& localFilename,
57 const wxString& globalFilename,
58 long style)
59 : wxConfigBase(strAppName, strVendor, localFilename, globalFilename, style)
60
61#if 0 // This is too complex for some compilers, e.g. BC++ 5.01
62 : wxConfigBase((strAppName.empty() && wxTheApp) ? wxTheApp->GetAppName()
63 : strAppName,
64 strVendor.empty() ? (wxTheApp ? wxTheApp->GetVendorName()
65 : strAppName)
66 : strVendor,
67 localFilename, globalFilename, style)
68#endif
69{
70 if (strAppName.empty() && wxTheApp)
71 SetAppName(wxTheApp->GetAppName());
72 if (strVendor.empty() && wxTheApp)
73 SetVendorName(wxTheApp->GetVendorName());
74
75 m_strLocalFilename = localFilename;
76 if (m_strLocalFilename.empty())
77 {
78 m_strLocalFilename = GetAppName() + wxT(".ini");
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]) &&
84 m_strLocalFilename.Find(wxT('.')) == wxNOT_FOUND )
85 {
86 m_strLocalFilename << wxT(".ini");
87 }
88
89 // set root path
90 SetPath(wxEmptyString);
91}
92
93wxIniConfig::~wxIniConfig()
94{
95}
96
97// ----------------------------------------------------------------------------
98// path management
99// ----------------------------------------------------------------------------
100
101void wxIniConfig::SetPath(const wxString& strPath)
102{
103 wxArrayString aParts;
104
105 if ( strPath.empty() ) {
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
119 size_t nPartsCount = aParts.Count();
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];
128 for ( size_t nPart = 1; nPart < nPartsCount; nPart++ ) {
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
137 wxASSERT( (m_strPath.empty() || m_strPath.Last() != PATH_SEP_REPLACE) &&
138 (m_strGroup == wxString(PATH_SEP_REPLACE) ||
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
149 if ( m_strGroup == wxString(PATH_SEP_REPLACE) ) {
150 // we're at the root level, nothing to do
151 }
152 else {
153 s_str << m_strGroup;
154 if ( !m_strPath.empty() )
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
164wxString wxIniConfig::GetPrivateKeyName(const wxString& szKey) const
165{
166 wxString strKey;
167
168 if ( !m_strPath.empty() )
169 strKey << m_strPath << PATH_SEP_REPLACE;
170
171 strKey << szKey;
172
173 return strKey;
174}
175
176wxString wxIniConfig::GetKeyName(const wxString& szKey) const
177{
178 wxString strKey;
179
180 if ( m_strGroup != wxString(PATH_SEP_REPLACE) )
181 strKey << m_strGroup << PATH_SEP_REPLACE;
182 if ( !m_strPath.empty() )
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
195bool wxIniConfig::GetFirstGroup(wxString& WXUNUSED(str), long& WXUNUSED(lIndex)) const
196{
197 wxFAIL_MSG("not implemented");
198
199 return false;
200}
201
202bool wxIniConfig::GetNextGroup (wxString& WXUNUSED(str), long& WXUNUSED(lIndex)) const
203{
204 wxFAIL_MSG("not implemented");
205
206 return false;
207}
208
209bool wxIniConfig::GetFirstEntry(wxString& WXUNUSED(str), long& WXUNUSED(lIndex)) const
210{
211 wxFAIL_MSG("not implemented");
212
213 return false;
214}
215
216bool wxIniConfig::GetNextEntry (wxString& WXUNUSED(str), long& WXUNUSED(lIndex)) const
217{
218 wxFAIL_MSG("not implemented");
219
220 return false;
221}
222
223// ----------------------------------------------------------------------------
224// misc info
225// ----------------------------------------------------------------------------
226
227// not implemented
228size_t wxIniConfig::GetNumberOfEntries(bool WXUNUSED(bRecursive)) const
229{
230 wxFAIL_MSG("not implemented");
231
232 return (size_t)-1;
233}
234
235size_t wxIniConfig::GetNumberOfGroups(bool WXUNUSED(bRecursive)) const
236{
237 wxFAIL_MSG("not implemented");
238
239 return (size_t)-1;
240}
241
242bool wxIniConfig::HasGroup(const wxString& WXUNUSED(strName)) const
243{
244 wxFAIL_MSG("not implemented");
245
246 return false;
247}
248
249bool wxIniConfig::HasEntry(const wxString& WXUNUSED(strName)) const
250{
251 wxFAIL_MSG("not implemented");
252
253 return false;
254}
255
256// is current group empty?
257bool wxIniConfig::IsEmpty() const
258{
259 char szBuf[1024];
260
261 GetPrivateProfileString(m_strGroup, NULL, "",
262 szBuf, WXSIZEOF(szBuf), m_strLocalFilename);
263 if ( !::IsEmpty(szBuf) )
264 return false;
265
266 GetProfileString(m_strGroup, NULL, "", szBuf, WXSIZEOF(szBuf));
267 if ( !::IsEmpty(szBuf) )
268 return false;
269
270 return true;
271}
272
273// ----------------------------------------------------------------------------
274// read/write
275// ----------------------------------------------------------------------------
276
277bool wxIniConfig::DoReadString(const wxString& szKey, wxString *pstr) const
278{
279 wxConfigPathChanger path(this, szKey);
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, "",
288 szBuf, WXSIZEOF(szBuf), m_strLocalFilename);
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
295 if ( ::IsEmpty(szBuf) )
296 return false;
297
298 *pstr = szBuf;
299 return true;
300}
301
302bool wxIniConfig::DoReadLong(const wxString& szKey, long *pl) const
303{
304 wxConfigPathChanger path(this, szKey);
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
312 long lVal = GetPrivateProfileInt(m_strGroup, strKey, nMagic, m_strLocalFilename);
313 if ( lVal != nMagic ) {
314 // the value was read from the file
315 *pl = lVal;
316 return true;
317 }
318
319 // is it really nMagic?
320 lVal = GetPrivateProfileInt(m_strGroup, strKey, nMagic2, m_strLocalFilename);
321 if ( lVal != nMagic2 ) {
322 // the nMagic it returned was indeed read from the file
323 *pl = lVal;
324 return true;
325 }
326
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
331 // no, it was just returning the default value, so now look in win.ini
332 *pl = GetProfileInt(GetVendorName(), GetKeyName(szKey), *pl);
333
334 return true;
335#endif
336 return false ;
337}
338
339bool wxIniConfig::DoWriteString(const wxString& szKey, const wxString& szValue)
340{
341 wxConfigPathChanger path(this, szKey);
342 wxString strKey = GetPrivateKeyName(path.Name());
343
344 bool bOk = WritePrivateProfileString(m_strGroup, strKey,
345 szValue, m_strLocalFilename) != 0;
346
347 if ( !bOk )
348 wxLogLastError(wxT("WritePrivateProfileString"));
349
350 return bOk;
351}
352
353bool wxIniConfig::DoWriteLong(const wxString& szKey, long lValue)
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
365 return WritePrivateProfileString(NULL, NULL, NULL, m_strLocalFilename) != 0;
366}
367
368// ----------------------------------------------------------------------------
369// delete
370// ----------------------------------------------------------------------------
371
372bool wxIniConfig::DeleteEntry(const wxString& szKey, bool bGroupIfEmptyAlso)
373{
374 // passing NULL as value to WritePrivateProfileString deletes the key
375 wxConfigPathChanger path(this, szKey);
376 wxString strKey = GetPrivateKeyName(path.Name());
377
378 if (WritePrivateProfileString(m_strGroup, strKey,
379 (const char*) NULL, m_strLocalFilename) == 0)
380 return false;
381
382 if ( !bGroupIfEmptyAlso || !IsEmpty() )
383 return true;
384
385 // delete the current group too
386 bool bOk = WritePrivateProfileString(m_strGroup, NULL,
387 NULL, m_strLocalFilename) != 0;
388
389 if ( !bOk )
390 wxLogLastError(wxT("WritePrivateProfileString"));
391
392 return bOk;
393}
394
395bool wxIniConfig::DeleteGroup(const wxString& szKey)
396{
397 wxConfigPathChanger path(this, szKey);
398
399 // passing NULL as section name to WritePrivateProfileString deletes the
400 // whole section according to the docs
401 bool bOk = WritePrivateProfileString(path.Name(), NULL,
402 NULL, m_strLocalFilename) != 0;
403
404 if ( !bOk )
405 wxLogLastError(wxT("WritePrivateProfileString"));
406
407 return bOk;
408}
409
410#ifndef MAX_PATH
411#define MAX_PATH 256
412#endif
413
414bool wxIniConfig::DeleteAll()
415{
416 // first delete our group in win.ini
417 WriteProfileString(GetVendorName(), NULL, NULL);
418
419 // then delete our own ini file
420 char szBuf[MAX_PATH];
421 size_t nRc = GetWindowsDirectory(szBuf, WXSIZEOF(szBuf));
422 if ( nRc == 0 )
423 {
424 wxLogLastError(wxT("GetWindowsDirectory"));
425 }
426 else if ( nRc > WXSIZEOF(szBuf) )
427 {
428 wxFAIL_MSG(wxT("buffer is too small for Windows directory."));
429 }
430
431 wxString strFile = szBuf;
432 strFile << '\\' << m_strLocalFilename;
433
434 if ( wxFile::Exists(strFile) && !wxRemoveFile(strFile) ) {
435 wxLogSysError(_("Can't delete the INI file '%s'"), strFile.c_str());
436 return false;
437 }
438
439 return true;
440}
441
442bool wxIniConfig::RenameEntry(const wxString& WXUNUSED(oldName),
443 const wxString& WXUNUSED(newName))
444{
445 // Not implemented
446 return false;
447}
448
449bool wxIniConfig::RenameGroup(const wxString& WXUNUSED(oldName),
450 const wxString& WXUNUSED(newName))
451{
452 // Not implemented
453 return false;
454}
455
456#endif
457 // wxUSE_CONFIG && wxUSE_UNICODE