]> git.saurik.com Git - wxWidgets.git/blob - src/common/config.cpp
wxString::Scanf() removed because can't be implemented portably
[wxWidgets.git] / src / common / config.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: config.cpp
3 // Purpose: implementation of wxConfig class
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 07.04.98
7 // RCS-ID: $Id$
8 // Copyright: (c) 1997 Karsten Ballüder Ballueder@usa.net
9 // Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
10 // Licence: wxWindows license
11 ///////////////////////////////////////////////////////////////////////////////
12
13 // ============================================================================
14 // declarations
15 // ============================================================================
16
17 // ----------------------------------------------------------------------------
18 // headers
19 // ----------------------------------------------------------------------------
20 #ifdef __GNUG__
21 #pragma implementation "config.h"
22 #endif
23
24 #include "wx/wxprec.h"
25
26 #ifdef __BORLANDC__
27 #pragma hdrstop
28 #endif //__BORLANDC__
29
30 #ifndef WX_PRECOMP
31 #include <wx/string.h>
32 #include <wx/intl.h>
33 #endif //WX_PRECOMP
34
35 #include <wx/app.h>
36 #include <wx/file.h>
37 #include <wx/log.h>
38 #include <wx/textfile.h>
39 #include <wx/config.h>
40 #include <wx/fileconf.h>
41
42 #include <ctype.h> // for isalnum()
43
44 // ----------------------------------------------------------------------------
45 // global and class static variables
46 // ----------------------------------------------------------------------------
47
48 wxConfig *wxConfig::ms_pConfig = NULL;
49
50 // ============================================================================
51 // implementation
52 // ============================================================================
53
54 // ----------------------------------------------------------------------------
55 // wxConfig
56 // ----------------------------------------------------------------------------
57 wxConfig::~wxConfig()
58 {
59 }
60
61 wxConfig *wxConfig::Set(wxConfig *pConfig)
62 {
63 wxConfig *pOld = ms_pConfig;
64 ms_pConfig = pConfig;
65 return pOld;
66 }
67
68 void wxConfig::Create()
69 {
70 ms_pConfig = wxTheApp->CreateConfig();
71 }
72
73 const char *wxConfig::Read(const char *szKey, const char *szDefault) const
74 {
75 static char s_szBuf[1024];
76 wxString s;
77 Read(&s, szKey, szDefault);
78 strncpy(s_szBuf, s, WXSIZEOF(s_szBuf));
79
80 return s_szBuf;
81 }
82
83 // ----------------------------------------------------------------------------
84 // Config::PathChanger
85 // ----------------------------------------------------------------------------
86
87 wxConfig::PathChanger::PathChanger(const wxConfig *pContainer,
88 const wxString& strEntry)
89 {
90 m_pContainer = (wxConfig *)pContainer;
91 wxString strPath = strEntry.Before(APPCONF_PATH_SEPARATOR);
92
93 // special case of "/keyname" when there is nothing before "/"
94 if ( strPath.IsEmpty() && strEntry[0] == APPCONF_PATH_SEPARATOR )
95 strPath = APPCONF_PATH_SEPARATOR;
96
97 if ( !strPath.IsEmpty() ) {
98 // do change the path
99 m_bChanged = TRUE;
100 m_strName = strEntry.Right(APPCONF_PATH_SEPARATOR);
101 m_strOldPath = m_pContainer->GetPath();
102 m_strOldPath += APPCONF_PATH_SEPARATOR;
103 m_pContainer->SetPath(strPath);
104 }
105 else {
106 // it's a name only, without path - nothing to do
107 m_bChanged = FALSE;
108 m_strName = strEntry;
109 }
110 }
111
112 wxConfig::PathChanger::~PathChanger()
113 {
114 // only restore path if it was changed
115 if ( m_bChanged ) {
116 m_pContainer->SetPath(m_strOldPath);
117 }
118 }
119
120 // ----------------------------------------------------------------------------
121 // static & global functions
122 // ----------------------------------------------------------------------------
123
124 // understands both Unix and Windows (but only under Windows) environment
125 // variables expansion: i.e. $var, $(var) and ${var} are always understood
126 // and in addition under Windows %var% is also.
127 wxString ExpandEnvVars(const wxString& str)
128 {
129 wxString strResult;
130
131 // don't change the values the enum elements: they must be equal
132 // to the matching [closing] delimiter.
133 enum Bracket
134 {
135 Bracket_None,
136 Bracket_Normal = ')',
137 Bracket_Curly = '}',
138 #ifdef __WINDOWS__
139 Bracket_Windows = '%' // yeah, Windows people are a bit strange ;-)
140 #endif
141 };
142
143 uint m;
144 for ( uint n = 0; n < str.Len(); n++ ) {
145 switch ( str[n] ) {
146 #ifdef __WINDOWS__
147 case '%':
148 #endif //WINDOWS
149 case '$':
150 {
151 Bracket bracket;
152 #ifdef __WINDOWS__
153 if ( str[n] == '%' )
154 bracket = Bracket_Windows;
155 else
156 #endif //WINDOWS
157 if ( n == str.Len() - 1 ) {
158 bracket = Bracket_None;
159 }
160 else {
161 switch ( str[n + 1] ) {
162 case '(':
163 bracket = Bracket_Normal;
164 n++; // skip the bracket
165 break;
166
167 case '{':
168 bracket = Bracket_Curly;
169 n++; // skip the bracket
170 break;
171
172 default:
173 bracket = Bracket_None;
174 }
175 }
176
177 m = n + 1;
178
179 while ( m < str.Len() && (isalnum(str[m]) || str[m] == '_') )
180 m++;
181
182 wxString strVarName(str.c_str() + n + 1, m - n - 1);
183
184 const char *pszValue = getenv(strVarName);
185 if ( pszValue != NULL ) {
186 strResult += pszValue;
187 }
188 else {
189 // variable doesn't exist => don't change anything
190 #ifdef __WINDOWS__
191 if ( bracket != Bracket_Windows )
192 #endif
193 if ( bracket != Bracket_None )
194 strResult << str[n - 1];
195 strResult << str[n] << strVarName;
196 }
197
198 // check the closing bracket
199 if ( bracket != Bracket_None ) {
200 if ( m == str.Len() || str[m] != (char)bracket ) {
201 wxLogWarning("missing '%c' at position %d in '%s'.",
202 (char)bracket, m + 1, str.c_str());
203 }
204 else {
205 // skip closing bracket
206 if ( pszValue == NULL )
207 strResult << (char)bracket;
208 m++;
209 }
210 }
211
212 n = m - 1; // skip variable name
213 }
214 break;
215
216 case '\\':
217 n++;
218 // fall through
219
220 default:
221 strResult += str[n];
222 }
223 }
224
225 return strResult;
226 }
227
228 // this function is used to properly interpret '..' in path
229 void SplitPath(wxArrayString& aParts, const char *sz)
230 {
231 aParts.Empty();
232
233 wxString strCurrent;
234 const char *pc = sz;
235 for ( ;; ) {
236 if ( *pc == '\0' || *pc == APPCONF_PATH_SEPARATOR ) {
237 if ( strCurrent == "." ) {
238 // ignore
239 }
240 else if ( strCurrent == ".." ) {
241 // go up one level
242 if ( aParts.IsEmpty() )
243 wxLogWarning("'%s' has extra '..', ignored.", sz);
244 else
245 aParts.Remove(aParts.Count() - 1);
246
247 strCurrent.Empty();
248 }
249 else if ( !strCurrent.IsEmpty() ) {
250 aParts.Add(strCurrent);
251 strCurrent.Empty();
252 }
253 //else:
254 // could log an error here, but we prefer to ignore extra '/'
255
256 if ( *pc == '\0' )
257 return;
258 }
259 else
260 strCurrent += *pc;
261
262 pc++;
263 }
264 }
265