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