]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/iniconf.cpp
Fixed bug #778299 - wxTE_RICH2 causes SetValue to show control.
[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#ifndef WX_PRECOMP
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"
25#endif //WX_PRECOMP
26
27// Doesn't yet compile in Unicode mode
28
29#if wxUSE_CONFIG && !wxUSE_UNICODE
30
31#include "wx/dynarray.h"
32#include "wx/log.h"
33#include "wx/config.h"
34#include "wx/file.h"
35
36#include "wx/msw/iniconf.h"
37
38// _WINDOWS_ is defined when windows.h is included,
39// __WXMSW__ is defined for MS Windows compilation
40#if defined(__WXMSW__) && !defined(_WINDOWS_)
41 #include "wx/msw/wrapwin.h"
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
59wxIniConfig::wxIniConfig(const wxString& strAppName,
60 const wxString& strVendor,
61 const wxString& localFilename,
62 const wxString& globalFilename,
63 long style)
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()
68 : strAppName,
69 strVendor.IsEmpty() ? (wxTheApp ? wxTheApp->GetVendorName()
70 : strAppName)
71 : strVendor,
72 localFilename, globalFilename, style)
73#endif
74{
75 if (strAppName.IsEmpty() && wxTheApp)
76 SetAppName(wxTheApp->GetAppName());
77 if (strVendor.IsEmpty() && wxTheApp)
78 SetVendorName(wxTheApp->GetVendorName());
79
80 m_strLocalFilename = localFilename;
81 if (m_strLocalFilename.IsEmpty())
82 {
83 m_strLocalFilename = GetAppName() + wxT(".ini");
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]) &&
89 m_strLocalFilename.Find(wxT('.')) == wxNOT_FOUND )
90 {
91 m_strLocalFilename << wxT(".ini");
92 }
93
94 // set root path
95 SetPath(wxEmptyString);
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
124 size_t nPartsCount = aParts.Count();
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];
133 for ( size_t nPart = 1; nPart < nPartsCount; nPart++ ) {
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) &&
143 (m_strGroup == wxString(PATH_SEP_REPLACE) ||
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
154 if ( m_strGroup == wxString(PATH_SEP_REPLACE) ) {
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
169wxString wxIniConfig::GetPrivateKeyName(const wxString& szKey) const
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
181wxString wxIniConfig::GetKeyName(const wxString& szKey) const
182{
183 wxString strKey;
184
185 if ( m_strGroup != wxString(PATH_SEP_REPLACE) )
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
200bool wxIniConfig::GetFirstGroup(wxString& WXUNUSED(str), long& WXUNUSED(lIndex)) const
201{
202 wxFAIL_MSG("not implemented");
203
204 return false;
205}
206
207bool wxIniConfig::GetNextGroup (wxString& WXUNUSED(str), long& WXUNUSED(lIndex)) const
208{
209 wxFAIL_MSG("not implemented");
210
211 return false;
212}
213
214bool wxIniConfig::GetFirstEntry(wxString& WXUNUSED(str), long& WXUNUSED(lIndex)) const
215{
216 wxFAIL_MSG("not implemented");
217
218 return false;
219}
220
221bool wxIniConfig::GetNextEntry (wxString& WXUNUSED(str), long& WXUNUSED(lIndex)) const
222{
223 wxFAIL_MSG("not implemented");
224
225 return false;
226}
227
228// ----------------------------------------------------------------------------
229// misc info
230// ----------------------------------------------------------------------------
231
232// not implemented
233size_t wxIniConfig::GetNumberOfEntries(bool WXUNUSED(bRecursive)) const
234{
235 wxFAIL_MSG("not implemented");
236
237 return (size_t)-1;
238}
239
240size_t wxIniConfig::GetNumberOfGroups(bool WXUNUSED(bRecursive)) const
241{
242 wxFAIL_MSG("not implemented");
243
244 return (size_t)-1;
245}
246
247bool wxIniConfig::HasGroup(const wxString& WXUNUSED(strName)) const
248{
249 wxFAIL_MSG("not implemented");
250
251 return false;
252}
253
254bool wxIniConfig::HasEntry(const wxString& WXUNUSED(strName)) const
255{
256 wxFAIL_MSG("not implemented");
257
258 return false;
259}
260
261// is current group empty?
262bool wxIniConfig::IsEmpty() const
263{
264 char szBuf[1024];
265
266 GetPrivateProfileString(m_strGroup, NULL, "",
267 szBuf, WXSIZEOF(szBuf), m_strLocalFilename);
268 if ( !::IsEmpty(szBuf) )
269 return false;
270
271 GetProfileString(m_strGroup, NULL, "", szBuf, WXSIZEOF(szBuf));
272 if ( !::IsEmpty(szBuf) )
273 return false;
274
275 return true;
276}
277
278// ----------------------------------------------------------------------------
279// read/write
280// ----------------------------------------------------------------------------
281
282bool wxIniConfig::DoReadString(const wxString& szKey, wxString *pstr) const
283{
284 wxConfigPathChanger path(this, szKey);
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, "",
293 szBuf, WXSIZEOF(szBuf), m_strLocalFilename);
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
300 if ( ::IsEmpty(szBuf) )
301 return false;
302
303 *pstr = szBuf;
304 return true;
305}
306
307bool wxIniConfig::DoReadLong(const wxString& szKey, long *pl) const
308{
309 wxConfigPathChanger path(this, szKey);
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
317 long lVal = GetPrivateProfileInt(m_strGroup, strKey, nMagic, m_strLocalFilename);
318 if ( lVal != nMagic ) {
319 // the value was read from the file
320 *pl = lVal;
321 return true;
322 }
323
324 // is it really nMagic?
325 lVal = GetPrivateProfileInt(m_strGroup, strKey, nMagic2, m_strLocalFilename);
326 if ( lVal != nMagic2 ) {
327 // the nMagic it returned was indeed read from the file
328 *pl = lVal;
329 return true;
330 }
331
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
336 // no, it was just returning the default value, so now look in win.ini
337 *pl = GetProfileInt(GetVendorName(), GetKeyName(szKey), *pl);
338
339 return true;
340#endif
341 return false ;
342}
343
344bool wxIniConfig::DoWriteString(const wxString& szKey, const wxString& szValue)
345{
346 wxConfigPathChanger path(this, szKey);
347 wxString strKey = GetPrivateKeyName(path.Name());
348
349 bool bOk = WritePrivateProfileString(m_strGroup, strKey,
350 szValue, m_strLocalFilename) != 0;
351
352 if ( !bOk )
353 wxLogLastError(wxT("WritePrivateProfileString"));
354
355 return bOk;
356}
357
358bool wxIniConfig::DoWriteLong(const wxString& szKey, long lValue)
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
370 return WritePrivateProfileString(NULL, NULL, NULL, m_strLocalFilename) != 0;
371}
372
373// ----------------------------------------------------------------------------
374// delete
375// ----------------------------------------------------------------------------
376
377bool wxIniConfig::DeleteEntry(const wxString& szKey, bool bGroupIfEmptyAlso)
378{
379 // passing NULL as value to WritePrivateProfileString deletes the key
380 wxConfigPathChanger path(this, szKey);
381 wxString strKey = GetPrivateKeyName(path.Name());
382
383 if (WritePrivateProfileString(m_strGroup, strKey,
384 (const char*) NULL, m_strLocalFilename) == 0)
385 return false;
386
387 if ( !bGroupIfEmptyAlso || !IsEmpty() )
388 return true;
389
390 // delete the current group too
391 bool bOk = WritePrivateProfileString(m_strGroup, NULL,
392 NULL, m_strLocalFilename) != 0;
393
394 if ( !bOk )
395 wxLogLastError(wxT("WritePrivateProfileString"));
396
397 return bOk;
398}
399
400bool wxIniConfig::DeleteGroup(const wxString& szKey)
401{
402 wxConfigPathChanger path(this, szKey);
403
404 // passing NULL as section name to WritePrivateProfileString deletes the
405 // whole section according to the docs
406 bool bOk = WritePrivateProfileString(path.Name(), NULL,
407 NULL, m_strLocalFilename) != 0;
408
409 if ( !bOk )
410 wxLogLastError(wxT("WritePrivateProfileString"));
411
412 return bOk;
413}
414
415#ifndef MAX_PATH
416#define MAX_PATH 256
417#endif
418
419bool wxIniConfig::DeleteAll()
420{
421 // first delete our group in win.ini
422 WriteProfileString(GetVendorName(), NULL, NULL);
423
424 // then delete our own ini file
425 char szBuf[MAX_PATH];
426 size_t nRc = GetWindowsDirectory(szBuf, WXSIZEOF(szBuf));
427 if ( nRc == 0 )
428 {
429 wxLogLastError(wxT("GetWindowsDirectory"));
430 }
431 else if ( nRc > WXSIZEOF(szBuf) )
432 {
433 wxFAIL_MSG(wxT("buffer is too small for Windows directory."));
434 }
435
436 wxString strFile = szBuf;
437 strFile << '\\' << m_strLocalFilename;
438
439 if ( wxFile::Exists(strFile) && !wxRemoveFile(strFile) ) {
440 wxLogSysError(_("Can't delete the INI file '%s'"), strFile.c_str());
441 return false;
442 }
443
444 return true;
445}
446
447bool wxIniConfig::RenameEntry(const wxString& WXUNUSED(oldName),
448 const wxString& WXUNUSED(newName))
449{
450 // Not implemented
451 return false;
452}
453
454bool wxIniConfig::RenameGroup(const wxString& WXUNUSED(oldName),
455 const wxString& WXUNUSED(newName))
456{
457 // Not implemented
458 return false;
459}
460
461#endif
462 // wxUSE_CONFIG && wxUSE_UNICODE