]> git.saurik.com Git - wxWidgets.git/blob - src/msw/regconf.cpp
IsModified() function now works correctly
[wxWidgets.git] / src / msw / regconf.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: msw/regconf.cpp
3 // Purpose:
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 27.04.98
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "regconf.h"
14 #endif
15
16 // ============================================================================
17 // declarations
18 // ============================================================================
19
20 // ----------------------------------------------------------------------------
21 // headers
22 // ----------------------------------------------------------------------------
23
24 #ifdef __GNUG__
25 #pragma implementation "regconf.h"
26 #endif
27
28 #include "wx/wxprec.h"
29
30 #ifdef __BORLANDC__
31 #pragma hdrstop
32 #endif //__BORLANDC__
33
34 #ifndef WX_PRECOMP
35 #include <wx/string.h>
36 #endif //WX_PRECOMP
37
38 #include <wx/log.h>
39 #include <wx/config.h>
40 #include <wx/msw/registry.h>
41 #include <wx/msw/regconf.h>
42
43 // ----------------------------------------------------------------------------
44 // constants
45 // ----------------------------------------------------------------------------
46
47 // we put our data in HKLM\SOFTWARE_KEY\appname
48 #define SOFTWARE_KEY wxString("Software\\")
49
50 // ----------------------------------------------------------------------------
51 // global functions
52 // ----------------------------------------------------------------------------
53
54 // get the value if the key is opened and it exists
55 bool TryGetValue(const wxRegKey& key, const wxString& str, wxString& strVal)
56 {
57 return key.IsOpened() && key.HasValue(str) && key.QueryValue(str, strVal);
58 }
59
60 bool TryGetValue(const wxRegKey& key, const wxString& str, long *plVal)
61 {
62 return key.IsOpened() && key.HasValue(str) && key.QueryValue(str, plVal);
63 }
64
65 // ============================================================================
66 // implementation
67 // ============================================================================
68
69 // ----------------------------------------------------------------------------
70 // ctor/dtor
71 // ----------------------------------------------------------------------------
72 wxRegConfig::wxRegConfig(const wxString& strRoot)
73 : m_keyLocalRoot(wxRegKey::HKCU, SOFTWARE_KEY + strRoot),
74 m_keyLocal(m_keyLocalRoot, ""),
75 m_keyGlobalRoot(wxRegKey::HKLM, SOFTWARE_KEY + strRoot),
76 m_keyGlobal(m_keyGlobalRoot, "")
77 {
78 // Create() will Open() if key already exists
79 m_keyLocalRoot.Create();
80
81 wxLogNull nolog;
82 m_keyGlobalRoot.Open();
83 }
84
85 wxRegConfig::~wxRegConfig()
86 {
87 // nothing to do - key will be closed in their dtors
88 }
89
90 // ----------------------------------------------------------------------------
91 // path management
92 // ----------------------------------------------------------------------------
93 void wxRegConfig::SetPath(const wxString& strPath)
94 {
95 wxArrayString aParts;
96
97 if ( strPath.IsEmpty() )
98 return;
99
100 if ( strPath[0] == APPCONF_PATH_SEPARATOR ) {
101 // absolute path
102 wxSplitPath(aParts, strPath);
103 }
104 else {
105 // relative path, combine with current one
106 wxString strFullPath = GetPath();
107 strFullPath << APPCONF_PATH_SEPARATOR << strPath;
108 wxSplitPath(aParts, strFullPath);
109 }
110
111 // recombine path parts in one variable
112 wxString strRegPath;
113 m_strPath.Empty();
114 for ( uint n = 0; n < aParts.Count(); n++ ) {
115 strRegPath << '\\' << aParts[n];
116 m_strPath << APPCONF_PATH_SEPARATOR << aParts[n];
117 }
118
119 // change current key(s)
120 m_keyLocal.SetName(m_keyLocalRoot, strRegPath);
121 m_keyGlobal.SetName(m_keyGlobalRoot, strRegPath);
122 m_keyLocal.Create();
123
124 wxLogNull nolog;
125 m_keyGlobal.Open();
126 }
127
128 // ----------------------------------------------------------------------------
129 // enumeration (works only with current group)
130 // ----------------------------------------------------------------------------
131
132 /*
133 We want to enumerate all local keys/values after the global ones, but, of
134 course, we don't want to repeat a key which appears locally as well as
135 globally twice.
136
137 We use the 15th bit of lIndex for distinction between global and local.
138 */
139
140 #define LOCAL_MASK 0x8000
141 #define IS_LOCAL_INDEX(l) (((l) & LOCAL_MASK) != 0)
142
143 bool wxRegConfig::GetFirstGroup(wxString& str, long& lIndex) const
144 {
145 lIndex = 0;
146 return GetNextGroup(str, lIndex);
147 }
148
149 bool wxRegConfig::GetNextGroup(wxString& str, long& lIndex) const
150 {
151 // are we already enumerating local entries?
152 if ( m_keyGlobal.IsOpened() && !IS_LOCAL_INDEX(lIndex) ) {
153 // try to find a global entry which doesn't appear locally
154 do {
155 if ( !m_keyGlobal.GetNextKey(str, lIndex) ) {
156 // no more global entries
157 lIndex |= LOCAL_MASK;
158 break;
159 }
160 } while( m_keyLocal.HasSubKey(str) );
161 }
162
163 // much easier with local entries: get the next one we find
164 // (don't forget to clear our flag bit and set it again later)
165 lIndex &= ~LOCAL_MASK;
166 bool bOk = m_keyLocal.GetNextKey(str, lIndex);
167 lIndex |= LOCAL_MASK;
168
169 return bOk;
170 }
171
172 bool wxRegConfig::GetFirstEntry(wxString& str, long& lIndex) const
173 {
174 lIndex = 0;
175 return GetNextEntry(str, lIndex);
176 }
177
178 bool wxRegConfig::GetNextEntry(wxString& str, long& lIndex) const
179 {
180 // are we already enumerating local entries?
181 if ( m_keyGlobal.IsOpened() && !IS_LOCAL_INDEX(lIndex) ) {
182 // try to find a global entry which doesn't appear locally
183 do {
184 if ( !m_keyGlobal.GetNextValue(str, lIndex) ) {
185 // no more global entries
186 lIndex |= LOCAL_MASK;
187 break;
188 }
189 } while( m_keyLocal.HasValue(str) );
190 }
191
192 // much easier with local entries: get the next one we find
193 // (don't forget to clear our flag bit and set it again later)
194 lIndex &= ~LOCAL_MASK;
195 bool bOk = m_keyLocal.GetNextValue(str, lIndex);
196 lIndex |= LOCAL_MASK;
197
198 return bOk;
199 }
200
201 uint wxRegConfig::GetNumberOfEntries() const
202 {
203 uint nEntries = 0;
204
205 // dummy vars
206 wxString str;
207 long l;
208 bool bCont = GetFirstEntry(str, l);
209 while ( bCont ) {
210 nEntries++;
211
212 bCont = GetNextEntry(str, l);
213 }
214
215 return nEntries;
216 }
217
218 uint wxRegConfig::GetNumberOfGroups() const
219 {
220 uint nGroups = 0;
221
222 // dummy vars
223 wxString str;
224 long l;
225 bool bCont = GetFirstGroup(str, l);
226 while ( bCont ) {
227 nGroups++;
228
229 bCont = GetNextGroup(str, l);
230 }
231
232 return nGroups;
233 }
234
235 // ----------------------------------------------------------------------------
236 // tests for existence
237 // ----------------------------------------------------------------------------
238
239 bool wxRegConfig::HasGroup(const wxString& strName) const
240 {
241 return m_keyLocal.HasSubKey(strName) || m_keyGlobal.HasSubKey(strName);
242 }
243
244 bool wxRegConfig::HasEntry(const wxString& strName) const
245 {
246 return m_keyLocal.HasValue(strName) || m_keyGlobal.HasValue(strName);
247 }
248
249 // ----------------------------------------------------------------------------
250 // reading/writing
251 // ----------------------------------------------------------------------------
252
253 bool wxRegConfig::Read(wxString& str,
254 const char *szKey,
255 const char *szDefault) const
256 {
257 PathChanger path(this, szKey);
258
259 bool bQueryGlobal = TRUE;
260
261 // if immutable key exists in global key we must check that it's not
262 // overriden by the local key with the same name
263 if ( IsImmutable(path.Name()) ) {
264 if ( TryGetValue(m_keyGlobal, path.Name(), str) ) {
265 if ( m_keyLocal.HasValue(path.Name()) ) {
266 wxLogWarning("User value for immutable key '%s' ignored.",
267 path.Name().c_str());
268 }
269
270 return TRUE;
271 }
272 else {
273 // don't waste time - it's not there anyhow
274 bQueryGlobal = FALSE;
275 }
276 }
277
278 // first try local key
279 if ( TryGetValue(m_keyLocal, path.Name(), str) ||
280 (bQueryGlobal && TryGetValue(m_keyGlobal, path.Name(), str)) ) {
281 return TRUE;
282 }
283
284 // default value
285 str = szDefault;
286 return FALSE;
287 }
288
289 bool wxRegConfig::Read(long &lValue, const char *szKey, long lDefault) const
290 {
291 PathChanger path(this, szKey);
292
293 bool bQueryGlobal = TRUE;
294
295 // if immutable key exists in global key we must check that it's not
296 // overriden by the local key with the same name
297 if ( IsImmutable(path.Name()) ) {
298 if ( TryGetValue(m_keyGlobal, path.Name(), &lValue) ) {
299 if ( m_keyLocal.HasValue(path.Name()) ) {
300 wxLogWarning("User value for immutable key '%s' ignored.",
301 path.Name().c_str());
302 }
303
304 return TRUE;
305 }
306 else {
307 // don't waste time - it's not there anyhow
308 bQueryGlobal = FALSE;
309 }
310 }
311
312 // first try local key
313 if ( TryGetValue(m_keyLocal, path.Name(), &lValue) ||
314 (bQueryGlobal && TryGetValue(m_keyGlobal, path.Name(), &lValue)) ) {
315 return TRUE;
316 }
317
318 // default
319 lValue = lDefault;
320 return FALSE;
321 }
322
323 bool wxRegConfig::Write(const char *szKey, const char *szValue)
324 {
325 PathChanger path(this, szKey);
326
327 if ( IsImmutable(path.Name()) ) {
328 wxLogError("Can't change immutable entry '%s'.", path.Name().c_str());
329 return FALSE;
330 }
331
332 return m_keyLocal.SetValue(path.Name(), szValue);
333 }
334
335 bool wxRegConfig::Write(const char *szKey, long lValue)
336 {
337 PathChanger path(this, szKey);
338
339 if ( IsImmutable(path.Name()) ) {
340 wxLogError("Can't change immutable entry '%s'.", path.Name().c_str());
341 return FALSE;
342 }
343
344 return m_keyLocal.SetValue(path.Name(), lValue);
345 }
346
347 // ----------------------------------------------------------------------------
348 // deleting
349 // ----------------------------------------------------------------------------
350 bool wxRegConfig::DeleteEntry(const char *szValue, bool bGroupIfEmptyAlso)
351 {
352 PathChanger path(this, szValue);
353
354 if ( !m_keyLocal.DeleteValue(path.Name()) )
355 return FALSE;
356
357 if ( !m_keyLocal.HasSubkeys() ) {
358 wxString strKey = GetPath().Right(APPCONF_PATH_SEPARATOR);
359 SetPath(".."); // changes m_keyLocal
360 return m_keyLocal.DeleteKey(strKey);
361 }
362
363 return TRUE;
364 }
365
366 bool wxRegConfig::DeleteGroup(const char *szKey)
367 {
368 PathChanger path(this, szKey);
369
370 return m_keyLocal.DeleteKey(path.Name());
371 }
372
373 bool wxRegConfig::DeleteAll()
374 {
375 m_keyLocal.Close();
376 m_keyGlobal.Close();
377
378 bool bOk = m_keyLocalRoot.DeleteSelf();
379 if ( bOk )
380 bOk = m_keyGlobalRoot.DeleteSelf();
381
382 return bOk;
383 }