]> git.saurik.com Git - wxWidgets.git/blob - src/msw/regconf.cpp
registry based implementation of wxConfig (wxRegConfig)
[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 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19 #include <wx/wx.h>
20 #include <wx/config.h>
21 #include <wx/regconf.h>
22 #include <wx/registry.h>
23
24 // ----------------------------------------------------------------------------
25 // constants
26 // ----------------------------------------------------------------------------
27
28 // we put our data in HKLM\SOFTWARE_KEY\appname
29 #define SOFTWARE_KEY wxString("Software\\")
30
31 // ----------------------------------------------------------------------------
32 // global functions
33 // ----------------------------------------------------------------------------
34
35 // get the value if the key is opened and it exists
36 bool TryGetValue(const wxRegKey& key, const wxString& str, wxString& strVal)
37 {
38 return key.IsOpened() && key.HasValue(str) && key.QueryValue(str, strVal);
39 }
40
41 bool TryGetValue(const wxRegKey& key, const wxString& str, long *plVal)
42 {
43 return key.IsOpened() && key.HasValue(str) && key.QueryValue(str, plVal);
44 }
45
46 // ============================================================================
47 // implementation
48 // ============================================================================
49
50 // ----------------------------------------------------------------------------
51 // ctor/dtor
52 // ----------------------------------------------------------------------------
53 wxRegConfig::wxRegConfig(const wxString& strRoot)
54 : m_keyLocalRoot(wxRegKey::HKCU, SOFTWARE_KEY + strRoot),
55 m_keyLocal(m_keyLocalRoot, ""),
56 m_keyGlobalRoot(wxRegKey::HKLM, SOFTWARE_KEY + strRoot),
57 m_keyGlobal(m_keyGlobalRoot, "")
58 {
59 // Create() will Open() if key already exists
60 m_keyLocalRoot.Create();
61
62 wxLogNull nolog;
63 m_keyGlobalRoot.Open();
64 }
65
66 wxRegConfig::~wxRegConfig()
67 {
68 // nothing to do - key will be closed in their dtors
69 }
70
71 // ----------------------------------------------------------------------------
72 // path management
73 // ----------------------------------------------------------------------------
74 void wxRegConfig::SetPath(const wxString& strPath)
75 {
76 ArrayString aParts;
77
78 if ( strPath.IsEmpty() )
79 return;
80
81 if ( strPath[0] == APPCONF_PATH_SEPARATOR ) {
82 // absolute path
83 SplitPath(aParts, strPath);
84 }
85 else {
86 // relative path, combine with current one
87 wxString strFullPath = GetPath();
88 strFullPath << APPCONF_PATH_SEPARATOR << strPath;
89 SplitPath(aParts, strFullPath);
90 }
91
92 // recombine path parts in one variable
93 wxString strRegPath;
94 m_strPath.Empty();
95 for ( uint n = 0; n < aParts.Count(); n++ ) {
96 strRegPath << '\\' << aParts[n];
97 m_strPath << APPCONF_PATH_SEPARATOR << aParts[n];
98 }
99
100 // change current key(s)
101 m_keyLocal.SetName(m_keyLocalRoot, strRegPath);
102 m_keyGlobal.SetName(m_keyGlobalRoot, strRegPath);
103 m_keyLocal.Create();
104
105 wxLogNull nolog;
106 m_keyGlobal.Open();
107 }
108
109 // ----------------------------------------------------------------------------
110 // enumeration (works only with current group)
111 // ----------------------------------------------------------------------------
112
113 /*
114 We want to enumerate all local keys/values after the global ones, but, of
115 course, we don't want to repeat a key which appears locally as well as
116 globally twice.
117
118 We use the 15th bit of lIndex for distinction between global and local.
119 */
120
121 #define LOCAL_MASK 0x8000
122 #define IS_LOCAL_INDEX(l) (((l) & LOCAL_MASK) != 0)
123
124 bool wxRegConfig::GetFirstGroup(wxString& str, long& lIndex)
125 {
126 lIndex = 0;
127 return GetNextGroup(str, lIndex);
128 }
129
130 bool wxRegConfig::GetNextGroup (wxString& str, long& lIndex)
131 {
132 // are we already enumerating local entries?
133 if ( m_keyGlobal.IsOpened() && !IS_LOCAL_INDEX(lIndex) ) {
134 // try to find a global entry which doesn't appear locally
135 do {
136 if ( !m_keyGlobal.GetNextKey(str, lIndex) ) {
137 // no more global entries
138 lIndex |= LOCAL_MASK;
139 break;
140 }
141 } while( m_keyLocal.HasSubKey(str) );
142 }
143
144 // much easier with local entries: get the next one we find
145 // (don't forget to clear our flag bit and set it again later)
146 lIndex &= ~LOCAL_MASK;
147 bool bOk = m_keyLocal.GetNextKey(str, lIndex);
148 lIndex |= LOCAL_MASK;
149
150 return bOk;
151 }
152
153 bool wxRegConfig::GetFirstEntry(wxString& str, long& lIndex)
154 {
155 lIndex = 0;
156 return GetNextGroup(str, lIndex);
157 }
158
159 bool wxRegConfig::GetNextEntry (wxString& str, long& lIndex)
160 {
161 // are we already enumerating local entries?
162 if ( m_keyGlobal.IsOpened() && !IS_LOCAL_INDEX(lIndex) ) {
163 // try to find a global entry which doesn't appear locally
164 do {
165 if ( !m_keyGlobal.GetNextKey(str, lIndex) ) {
166 // no more global entries
167 lIndex |= LOCAL_MASK;
168 break;
169 }
170 } while( m_keyLocal.HasSubKey(str) );
171 }
172
173 // much easier with local entries: get the next one we find
174 // (don't forget to clear our flag bit and set it again later)
175 lIndex &= ~LOCAL_MASK;
176 bool bOk = m_keyLocal.GetNextKey(str, lIndex);
177 lIndex |= LOCAL_MASK;
178
179 return bOk;
180 }
181
182 // ----------------------------------------------------------------------------
183 // reading/writing
184 // ----------------------------------------------------------------------------
185
186 bool wxRegConfig::Read(wxString& str,
187 const char *szKey,
188 const char *szDefault) const
189 {
190 PathChanger path(this, szKey);
191
192 bool bQueryGlobal = true;
193
194 // if immutable key exists in global key we must check that it's not
195 // overriden by the local key with the same name
196 if ( IsImmutable(path.Name()) ) {
197 if ( TryGetValue(m_keyGlobal, path.Name(), str) ) {
198 if ( m_keyLocal.HasValue(path.Name()) ) {
199 wxLogWarning("User value for immutable key '%s' ignored.",
200 path.Name().c_str());
201 }
202
203 return true;
204 }
205 else {
206 // don't waste time - it's not there anyhow
207 bQueryGlobal = false;
208 }
209 }
210
211 // first try local key
212 if ( TryGetValue(m_keyLocal, path.Name(), str) ||
213 (bQueryGlobal && TryGetValue(m_keyGlobal, path.Name(), str)) ) {
214 return true;
215 }
216
217 // default value
218 str = szDefault;
219 return false;
220 }
221
222 bool wxRegConfig::Read(long &lValue, const char *szKey, long lDefault) const
223 {
224 PathChanger path(this, szKey);
225
226 bool bQueryGlobal = true;
227
228 // if immutable key exists in global key we must check that it's not
229 // overriden by the local key with the same name
230 if ( IsImmutable(path.Name()) ) {
231 if ( TryGetValue(m_keyGlobal, path.Name(), &lValue) ) {
232 if ( m_keyLocal.HasValue(path.Name()) ) {
233 wxLogWarning("User value for immutable key '%s' ignored.",
234 path.Name().c_str());
235 }
236
237 return true;
238 }
239 else {
240 // don't waste time - it's not there anyhow
241 bQueryGlobal = false;
242 }
243 }
244
245 // first try local key
246 if ( TryGetValue(m_keyLocal, path.Name(), &lValue) ||
247 (bQueryGlobal && TryGetValue(m_keyGlobal, path.Name(), &lValue)) ) {
248 return true;
249 }
250
251 // default
252 lValue = lDefault;
253 return false;
254 }
255
256 bool wxRegConfig::Write(const char *szKey, const char *szValue)
257 {
258 PathChanger path(this, szKey);
259
260 if ( IsImmutable(path.Name()) ) {
261 wxLogError("Can't change immutable entry '%s'.", path.Name().c_str());
262 return false;
263 }
264
265 return m_keyLocal.SetValue(path.Name(), szValue);
266 }
267
268 bool wxRegConfig::Write(const char *szKey, long lValue)
269 {
270 PathChanger path(this, szKey);
271
272 if ( IsImmutable(path.Name()) ) {
273 wxLogError("Can't change immutable entry '%s'.", path.Name().c_str());
274 return false;
275 }
276
277 return m_keyLocal.SetValue(path.Name(), lValue);
278 }
279
280 // ----------------------------------------------------------------------------
281 // deleting
282 // ----------------------------------------------------------------------------
283 bool wxRegConfig::DeleteEntry(const char *szValue, bool bGroupIfEmptyAlso)
284 {
285 PathChanger path(this, szValue);
286
287 if ( !m_keyLocal.DeleteValue(path.Name()) )
288 return false;
289
290 if ( m_keyLocal.IsEmpty() ) {
291 wxString strKey = GetPath().Right(APPCONF_PATH_SEPARATOR);
292 SetPath(".."); // changes m_keyLocal
293 return m_keyLocal.DeleteKey(strKey);
294 }
295
296 return true;
297 }
298
299 bool wxRegConfig::DeleteGroup(const char *szKey)
300 {
301 PathChanger path(this, szKey);
302
303 return m_keyLocal.DeleteKey(path.Name());
304 }
305
306 bool wxRegConfig::DeleteAll()
307 {
308 // first of all, prevent the creation of new registry entries
309 Config::EnableAutosave(false);
310
311 m_keyLocal.Close();
312 m_keyGlobal.Close();
313
314 bool bOk = m_keyLocalRoot.DeleteSelf();
315 if ( bOk )
316 bOk = m_keyGlobalRoot.DeleteSelf();
317
318 return bOk;
319 }