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