]> git.saurik.com Git - wxWidgets.git/blob - include/wx/fileconf.h
added wxUpdateUI generation
[wxWidgets.git] / include / wx / fileconf.h
1 /*****************************************************************************\
2 * Project: CppLib: C++ library for Windows/UNIX platfroms *
3 * File: fileconf.h - file based implementation of Config *
4 *---------------------------------------------------------------------------*
5 * Language: C++ *
6 * Platfrom: Any *
7 *---------------------------------------------------------------------------*
8 * Classes: *
9 *---------------------------------------------------------------------------*
10 * Author: Vadim Zeitlin zeitlin@dptmaths.ens-cachan.fr> *
11 * adapted from earlier class by VZ & Karsten Ballüder *
12 * History: *
13 * 27.04.98 created *
14 \*****************************************************************************/
15
16 #ifndef _FILECONF_H
17 #define _FILECONF_H
18
19 #ifdef __GNUG__
20 #pragma interface "fileconf.h"
21 #endif
22
23 // ----------------------------------------------------------------------------
24 // compile options
25 // ----------------------------------------------------------------------------
26
27 // it won't compile without it anyhow
28 #ifndef USE_WXCONFIG
29 #error "Please define USE_WXCONFIG or remove fileconf.cpp from your makefile"
30 #endif // USE_WXCONFIG
31
32 // ----------------------------------------------------------------------------
33 // wxFileConfig
34 // ----------------------------------------------------------------------------
35
36 /*
37 wxFileConfig derives from base Config and implements file based config class,
38 i.e. it uses ASCII disk files to store the information. These files are
39 alternatively called INI, .conf or .rc in the documentation. They are
40 organized in groups or sections, which can nest (i.e. a group contains
41 subgroups, which contain their own subgroups &c). Each group has some
42 number of entries, which are "key = value" pairs. More precisely, the format
43 is:
44
45 # comments are allowed after either ';' or '#' (Win/UNIX standard)
46
47 # blank lines (as above) are ignored
48
49 # global entries are members of special (no name) top group
50 written_for = Windows
51 platform = Linux
52
53 # the start of the group 'Foo'
54 [Foo] # may put comments like this also
55 # following 3 lines are entries
56 key = value
57 another_key = " strings with spaces in the beginning should be quoted, \
58 otherwise the spaces are lost"
59 last_key = but you don't have to put " normally (nor quote them, like here)
60
61 # subgroup of the group 'Foo'
62 # (order is not important, only the name is: separator is '/', as in paths)
63 [Foo/Bar]
64 # entries prefixed with "!" are immutable, i.e. can't be changed if they are
65 # set in the system-wide config file
66 !special_key = value
67 bar_entry = whatever
68
69 [Foo/Bar/Fubar] # depth is (theoretically :-) unlimited
70 # may have the same name as key in another section
71 bar_entry = whatever not
72
73 You have {read/write/delete}Entry functions (guess what they do) and also
74 setCurrentPath to select current group. enum{Subgroups/Entries} allow you
75 to get all entries in the config file (in the current group). Finally,
76 flush() writes immediately all changed entries to disk (otherwise it would
77 be done automatically in dtor)
78
79 wxFileConfig manages not less than 2 config files for each program: global
80 and local (or system and user if you prefer). Entries are read from both of
81 them and the local entries override the global ones unless the latter is
82 immutable (prefixed with '!') in which case a warning message is generated
83 and local value is ignored. Of course, the changes are always written to local
84 file only.
85
86 @@@@ describe environment variable expansion
87 */
88
89 class wxFileConfig : public wxConfig
90 {
91 public:
92 // construct the "standard" full name for global (system-wide) and
93 // local (user-specific) config files from the base file name.
94 //
95 // the following are the filenames returned by this functions:
96 // global local
97 // Unix /etc/file.ext ~/.file
98 // Win %windir%\file.ext %USERPROFILE%\file.ext
99 //
100 // where file is the basename of szFile, ext is it's extension
101 // or .conf (Unix) or .ini (Win) if it has none
102 static wxString GetGlobalFileName(const char *szFile);
103 static wxString GetLocalFileName(const char *szFile);
104
105 // ctor & dtor
106 // if strGlobal is empty, only local config file is used
107 wxFileConfig(const wxString& strLocal,
108 const wxString& strGlobal = "");
109 // dtor will save unsaved data
110 virtual ~wxFileConfig();
111
112 // implement inherited pure virtual functions
113 virtual void SetPath(const wxString& strPath);
114 virtual const wxString& GetPath() const { return m_strPath; }
115
116 virtual bool GetFirstGroup(wxString& str, long& lIndex);
117 virtual bool GetNextGroup (wxString& str, long& lIndex);
118 virtual bool GetFirstEntry(wxString& str, long& lIndex);
119 virtual bool GetNextEntry (wxString& str, long& lIndex);
120
121 virtual uint GetNumberOfEntries(bool bRecursive = FALSE) const;
122 virtual uint GetNumberOfGroups(bool bRecursive = FALSE) const;
123
124 virtual bool HasGroup(const wxString& strName) const;
125 virtual bool HasEntry(const wxString& strName) const;
126
127 virtual bool Read(wxString *pstr, const char *szKey,
128 const char *szDefault = 0) const;
129 virtual const char *Read(const char *szKey,
130 const char *szDefault = 0) const;
131 virtual bool Read(long *pl, const char *szKey, long lDefault) const;
132 virtual long Read(const char *szKey, long lDefault) const
133 { return wxConfig::Read(szKey, lDefault); }
134 virtual bool Write(const char *szKey, const char *szValue);
135 virtual bool Write(const char *szKey, long lValue);
136 virtual bool Flush(bool bCurrentOnly = FALSE);
137
138 virtual bool DeleteEntry(const char *szKey, bool bGroupIfEmptyAlso);
139 virtual bool DeleteGroup(const char *szKey);
140 virtual bool DeleteAll();
141
142 public:
143 // fwd decl
144 class ConfigGroup;
145 class ConfigEntry;
146
147 // we store all lines of the local config file as a linked list in memory
148 class LineList
149 {
150 public:
151 // ctor
152 LineList(const wxString& str, LineList *pNext = NULL) : m_strLine(str)
153 { SetNext(pNext); SetPrev(NULL); }
154
155 //
156 LineList *Next() const { return m_pNext; }
157 LineList *Prev() const { return m_pPrev; }
158 void SetNext(LineList *pNext) { m_pNext = pNext; }
159 void SetPrev(LineList *pPrev) { m_pPrev = pPrev; }
160
161 //
162 void SetText(const wxString& str) { m_strLine = str; }
163 const wxString& Text() const { return m_strLine; }
164
165 private:
166 wxString m_strLine; // line contents
167 LineList *m_pNext, // next node
168 *m_pPrev; // previous one
169 };
170
171 // functions to work with this list
172 LineList *LineListAppend(const wxString& str);
173 LineList *LineListInsert(const wxString& str,
174 LineList *pLine); // NULL => Prepend()
175 void LineListRemove(LineList *pLine);
176 bool LineListIsEmpty();
177
178 private:
179 // put the object in the initial state
180 void Init();
181
182 // parse the whole file
183 void Parse(wxTextFile& file, bool bLocal);
184
185 // the same as SetPath("/")
186 void SetRootPath();
187
188 // member variables
189 // ----------------
190 LineList *m_linesHead, // head of the linked list
191 *m_linesTail; // tail
192
193 wxString m_strLocalFile, // local file name passed to ctor
194 m_strGlobalFile; // global
195 wxString m_strPath; // current path (not '/' terminated)
196
197 ConfigGroup *m_pRootGroup, // the top (unnamed) group
198 *m_pCurrentGroup; // the current group
199
200 //protected: --- if wxFileConfig::ConfigEntry is not public, functions in
201 // ConfigGroup such as Find/AddEntry can't return "ConfigEntry *"
202 public:
203 WX_DEFINE_SORTED_ARRAY(ConfigEntry *, ArrayEntries);
204 WX_DEFINE_SORTED_ARRAY(ConfigGroup *, ArrayGroups);
205
206 class ConfigEntry
207 {
208 private:
209 ConfigGroup *m_pParent; // group that contains us
210 wxString m_strName, // entry name
211 m_strValue; // value
212 bool m_bDirty, // changed since last read?
213 m_bImmutable; // can be overriden locally?
214 int m_nLine; // used if m_pLine == NULL only
215 LineList *m_pLine; // pointer to our line in the linked list
216 // or NULL if it was found in global file
217
218 public:
219 ConfigEntry(ConfigGroup *pParent, const wxString& strName, int nLine);
220
221 // simple accessors
222 const wxString& Name() const { return m_strName; }
223 const wxString& Value() const { return m_strValue; }
224 ConfigGroup *Group() const { return m_pParent; }
225 bool IsDirty() const { return m_bDirty; }
226 bool IsImmutable() const { return m_bImmutable; }
227 bool IsLocal() const { return m_pLine != 0; }
228 int Line() const { return m_nLine; }
229 LineList *GetLine() const { return m_pLine; }
230
231 // modify entry attributes
232 void SetValue(const wxString& strValue, bool bUser = TRUE);
233 void SetDirty();
234 void SetLine(LineList *pLine);
235 };
236
237 class ConfigGroup
238 {
239 private:
240 wxFileConfig *m_pConfig; // config object we belong to
241 ConfigGroup *m_pParent; // parent group (NULL for root group)
242 ArrayEntries m_aEntries; // entries in this group
243 ArrayGroups m_aSubgroups; // subgroups
244 wxString m_strName; // group's name
245 bool m_bDirty; // if FALSE => all subgroups are not dirty
246 LineList *m_pLine; // pointer to our line in the linked list
247 ConfigEntry *m_pLastEntry; // last entry of this group in the local file
248 ConfigGroup *m_pLastGroup; // last subgroup
249
250 public:
251 // ctor
252 ConfigGroup(ConfigGroup *pParent, const wxString& strName, wxFileConfig *);
253
254 // dtor deletes all entries and subgroups also
255 ~ConfigGroup();
256
257 // simple accessors
258 const wxString& Name() const { return m_strName; }
259 ConfigGroup *Parent() const { return m_pParent; }
260 wxFileConfig *Config() const { return m_pConfig; }
261 bool IsDirty() const { return m_bDirty; }
262
263 bool IsEmpty() const { return Entries().IsEmpty() && Groups().IsEmpty(); }
264 const ArrayEntries& Entries() const { return m_aEntries; }
265 const ArrayGroups& Groups() const { return m_aSubgroups; }
266
267 // find entry/subgroup (NULL if not found)
268 ConfigGroup *FindSubgroup(const char *szName) const;
269 ConfigEntry *FindEntry (const char *szName) const;
270
271 // delete entry/subgroup, return FALSE if doesn't exist
272 bool DeleteSubgroup(const char *szName);
273 bool DeleteEntry(const char *szName);
274
275 // create new entry/subgroup returning pointer to newly created element
276 ConfigGroup *AddSubgroup(const wxString& strName);
277 ConfigEntry *AddEntry (const wxString& strName, int nLine = NOT_FOUND);
278
279 // will also recursively set parent's dirty flag
280 void SetDirty();
281 void SetLine(LineList *pLine);
282
283 // the new entries in this subgroup will be inserted after the last subgroup
284 // or, if there is none, after the last entry
285 void SetLastEntry(ConfigEntry *pLastEntry) { m_pLastEntry = pLastEntry; }
286 void SetLastGroup(ConfigGroup *pLastGroup) { m_pLastGroup = pLastGroup; }
287
288 wxString GetFullName() const;
289
290 // get the last line belonging to an entry/subgroup of this group
291 LineList *GetGroupLine();
292 LineList *GetLastEntryLine();
293 LineList *GetLastGroupLine();
294 };
295 };
296
297 #endif //_FILECONF_H
298