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