]> git.saurik.com Git - wxWidgets.git/blob - src/msw/regconf.cpp
Added wxExpr parser/lexer files which had somehow got lost;
[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/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 // reading/writing
188 // ----------------------------------------------------------------------------
189
190 bool wxRegConfig::Read(wxString& str,
191 const char *szKey,
192 const char *szDefault) const
193 {
194 PathChanger path(this, szKey);
195
196 bool bQueryGlobal = TRUE;
197
198 // if immutable key exists in global key we must check that it's not
199 // overriden by the local key with the same name
200 if ( IsImmutable(path.Name()) ) {
201 if ( TryGetValue(m_keyGlobal, path.Name(), str) ) {
202 if ( m_keyLocal.HasValue(path.Name()) ) {
203 wxLogWarning("User value for immutable key '%s' ignored.",
204 path.Name().c_str());
205 }
206
207 return TRUE;
208 }
209 else {
210 // don't waste time - it's not there anyhow
211 bQueryGlobal = FALSE;
212 }
213 }
214
215 // first try local key
216 if ( TryGetValue(m_keyLocal, path.Name(), str) ||
217 (bQueryGlobal && TryGetValue(m_keyGlobal, path.Name(), str)) ) {
218 return TRUE;
219 }
220
221 // default value
222 str = szDefault;
223 return FALSE;
224 }
225
226 bool wxRegConfig::Read(long &lValue, const char *szKey, long lDefault) const
227 {
228 PathChanger path(this, szKey);
229
230 bool bQueryGlobal = TRUE;
231
232 // if immutable key exists in global key we must check that it's not
233 // overriden by the local key with the same name
234 if ( IsImmutable(path.Name()) ) {
235 if ( TryGetValue(m_keyGlobal, path.Name(), &lValue) ) {
236 if ( m_keyLocal.HasValue(path.Name()) ) {
237 wxLogWarning("User value for immutable key '%s' ignored.",
238 path.Name().c_str());
239 }
240
241 return TRUE;
242 }
243 else {
244 // don't waste time - it's not there anyhow
245 bQueryGlobal = FALSE;
246 }
247 }
248
249 // first try local key
250 if ( TryGetValue(m_keyLocal, path.Name(), &lValue) ||
251 (bQueryGlobal && TryGetValue(m_keyGlobal, path.Name(), &lValue)) ) {
252 return TRUE;
253 }
254
255 // default
256 lValue = lDefault;
257 return FALSE;
258 }
259
260 bool wxRegConfig::Write(const char *szKey, const char *szValue)
261 {
262 PathChanger path(this, szKey);
263
264 if ( IsImmutable(path.Name()) ) {
265 wxLogError("Can't change immutable entry '%s'.", path.Name().c_str());
266 return FALSE;
267 }
268
269 return m_keyLocal.SetValue(path.Name(), szValue);
270 }
271
272 bool wxRegConfig::Write(const char *szKey, long lValue)
273 {
274 PathChanger path(this, szKey);
275
276 if ( IsImmutable(path.Name()) ) {
277 wxLogError("Can't change immutable entry '%s'.", path.Name().c_str());
278 return FALSE;
279 }
280
281 return m_keyLocal.SetValue(path.Name(), lValue);
282 }
283
284 // ----------------------------------------------------------------------------
285 // deleting
286 // ----------------------------------------------------------------------------
287 bool wxRegConfig::DeleteEntry(const char *szValue, bool bGroupIfEmptyAlso)
288 {
289 PathChanger path(this, szValue);
290
291 if ( !m_keyLocal.DeleteValue(path.Name()) )
292 return FALSE;
293
294 if ( m_keyLocal.IsEmpty() ) {
295 wxString strKey = GetPath().Right(APPCONF_PATH_SEPARATOR);
296 SetPath(".."); // changes m_keyLocal
297 return m_keyLocal.DeleteKey(strKey);
298 }
299
300 return TRUE;
301 }
302
303 bool wxRegConfig::DeleteGroup(const char *szKey)
304 {
305 PathChanger path(this, szKey);
306
307 return m_keyLocal.DeleteKey(path.Name());
308 }
309
310 bool wxRegConfig::DeleteAll()
311 {
312 // first of all, prevent the creation of new registry entries
313 Config::EnableAutosave(FALSE);
314
315 m_keyLocal.Close();
316 m_keyGlobal.Close();
317
318 bool bOk = m_keyLocalRoot.DeleteSelf();
319 if ( bOk )
320 bOk = m_keyGlobalRoot.DeleteSelf();
321
322 return bOk;
323 }