]> git.saurik.com Git - wxWidgets.git/blob - src/msw/iniconf.cpp
Removed /install/gtk/configure from cvs
[wxWidgets.git] / src / msw / iniconf.cpp
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
57 wxIniConfig::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
74 wxIniConfig::~wxIniConfig()
75 {
76 }
77
78 // ----------------------------------------------------------------------------
79 // path management
80 // ----------------------------------------------------------------------------
81
82 void 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
100 uint nPartsCount = aParts.Count();
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];
109 for ( uint nPart = 1; nPart < nPartsCount; nPart++ ) {
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
123 const 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
145 wxString 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
157 wxString 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
176 bool wxIniConfig::GetFirstGroup(wxString& str, long& lIndex) const
177 {
178 wxFAIL_MSG("not implemented");
179
180 return FALSE;
181 }
182
183 bool wxIniConfig::GetNextGroup (wxString& str, long& lIndex) const
184 {
185 wxFAIL_MSG("not implemented");
186
187 return FALSE;
188 }
189
190 bool wxIniConfig::GetFirstEntry(wxString& str, long& lIndex) const
191 {
192 wxFAIL_MSG("not implemented");
193
194 return FALSE;
195 }
196
197 bool 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
209 uint wxIniConfig::GetNumberOfEntries(bool bRecursive) const
210 {
211 wxFAIL_MSG("not implemented");
212
213 return (uint)-1;
214 }
215
216 uint wxIniConfig::GetNumberOfGroups(bool bRecursive) const
217 {
218 wxFAIL_MSG("not implemented");
219
220 return (uint)-1;
221 }
222
223 bool wxIniConfig::HasGroup(const wxString& strName) const
224 {
225 wxFAIL_MSG("not implemented");
226
227 return FALSE;
228 }
229
230 bool wxIniConfig::HasEntry(const wxString& strName) const
231 {
232 wxFAIL_MSG("not implemented");
233
234 return FALSE;
235 }
236
237 // is current group empty?
238 bool 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
258 bool 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
287 const 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
296 bool 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
329 long wxIniConfig::Read(const char *szKey, long lDefault) const
330 {
331 long lVal;
332 Read(&lVal, szKey, lDefault);
333
334 return lVal;
335 }
336
337 bool 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
351 bool 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
360 bool 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
370 bool 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
389 bool 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
404 bool 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];
411 uint nRc = GetWindowsDirectory(szBuf, WXSIZEOF(szBuf));
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 }