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