| 1 | /////////////////////////////////////////////////////////////////////////////// |
| 2 | // Name: wx/fileconf.h |
| 3 | // Purpose: wxFileConfig derivation of wxConfigBase |
| 4 | // Author: Vadim Zeitlin |
| 5 | // Modified by: |
| 6 | // Created: 07.04.98 (adapted from appconf.cpp) |
| 7 | // RCS-ID: $Id$ |
| 8 | // Copyright: (c) 1997 Karsten Ballueder & Vadim Zeitlin |
| 9 | // Ballueder@usa.net <zeitlin@dptmaths.ens-cachan.fr> |
| 10 | // Licence: wxWindows licence |
| 11 | /////////////////////////////////////////////////////////////////////////////// |
| 12 | |
| 13 | #ifndef _FILECONF_H |
| 14 | #define _FILECONF_H |
| 15 | |
| 16 | #include "wx/defs.h" |
| 17 | |
| 18 | #if wxUSE_CONFIG |
| 19 | |
| 20 | #include "wx/textfile.h" |
| 21 | #include "wx/string.h" |
| 22 | #include "wx/confbase.h" |
| 23 | #include "wx/filename.h" |
| 24 | |
| 25 | // ---------------------------------------------------------------------------- |
| 26 | // wxFileConfig |
| 27 | // ---------------------------------------------------------------------------- |
| 28 | |
| 29 | /* |
| 30 | wxFileConfig derives from base Config and implements file based config class, |
| 31 | i.e. it uses ASCII disk files to store the information. These files are |
| 32 | alternatively called INI, .conf or .rc in the documentation. They are |
| 33 | organized in groups or sections, which can nest (i.e. a group contains |
| 34 | subgroups, which contain their own subgroups &c). Each group has some |
| 35 | number of entries, which are "key = value" pairs. More precisely, the format |
| 36 | is: |
| 37 | |
| 38 | # comments are allowed after either ';' or '#' (Win/UNIX standard) |
| 39 | |
| 40 | # blank lines (as above) are ignored |
| 41 | |
| 42 | # global entries are members of special (no name) top group |
| 43 | written_for = Windows |
| 44 | platform = Linux |
| 45 | |
| 46 | # the start of the group 'Foo' |
| 47 | [Foo] # may put comments like this also |
| 48 | # following 3 lines are entries |
| 49 | key = value |
| 50 | another_key = " strings with spaces in the beginning should be quoted, \ |
| 51 | otherwise the spaces are lost" |
| 52 | last_key = but you don't have to put " normally (nor quote them, like here) |
| 53 | |
| 54 | # subgroup of the group 'Foo' |
| 55 | # (order is not important, only the name is: separator is '/', as in paths) |
| 56 | [Foo/Bar] |
| 57 | # entries prefixed with "!" are immutable, i.e. can't be changed if they are |
| 58 | # set in the system-wide config file |
| 59 | !special_key = value |
| 60 | bar_entry = whatever |
| 61 | |
| 62 | [Foo/Bar/Fubar] # depth is (theoretically :-) unlimited |
| 63 | # may have the same name as key in another section |
| 64 | bar_entry = whatever not |
| 65 | |
| 66 | You have {read/write/delete}Entry functions (guess what they do) and also |
| 67 | setCurrentPath to select current group. enum{Subgroups/Entries} allow you |
| 68 | to get all entries in the config file (in the current group). Finally, |
| 69 | flush() writes immediately all changed entries to disk (otherwise it would |
| 70 | be done automatically in dtor) |
| 71 | |
| 72 | wxFileConfig manages not less than 2 config files for each program: global |
| 73 | and local (or system and user if you prefer). Entries are read from both of |
| 74 | them and the local entries override the global ones unless the latter is |
| 75 | immutable (prefixed with '!') in which case a warning message is generated |
| 76 | and local value is ignored. Of course, the changes are always written to local |
| 77 | file only. |
| 78 | |
| 79 | The names of these files can be specified in a number of ways. First of all, |
| 80 | you can use the standard convention: using the ctor which takes 'strAppName' |
| 81 | parameter will probably be sufficient for 90% of cases. If, for whatever |
| 82 | reason you wish to use the files with some other names, you can always use the |
| 83 | second ctor. |
| 84 | |
| 85 | wxFileConfig also may automatically expand the values of environment variables |
| 86 | in the entries it reads: for example, if you have an entry |
| 87 | score_file = $HOME/.score |
| 88 | a call to Read(&str, "score_file") will return a complete path to .score file |
| 89 | unless the expansion was previously disabled with SetExpandEnvVars(false) call |
| 90 | (it's on by default, the current status can be retrieved with |
| 91 | IsExpandingEnvVars function). |
| 92 | */ |
| 93 | class WXDLLIMPEXP_FWD_BASE wxFileConfigGroup; |
| 94 | class WXDLLIMPEXP_FWD_BASE wxFileConfigEntry; |
| 95 | class WXDLLIMPEXP_FWD_BASE wxFileConfigLineList; |
| 96 | |
| 97 | #if wxUSE_STREAMS |
| 98 | class WXDLLIMPEXP_FWD_BASE wxInputStream; |
| 99 | class WXDLLIMPEXP_FWD_BASE wxOutputStream; |
| 100 | #endif // wxUSE_STREAMS |
| 101 | |
| 102 | class WXDLLIMPEXP_BASE wxFileConfig : public wxConfigBase |
| 103 | { |
| 104 | public: |
| 105 | // construct the "standard" full name for global (system-wide) and |
| 106 | // local (user-specific) config files from the base file name. |
| 107 | // |
| 108 | // the following are the filenames returned by this functions: |
| 109 | // global local |
| 110 | // Unix /etc/file.ext ~/.file |
| 111 | // Win %windir%\file.ext %USERPROFILE%\file.ext |
| 112 | // |
| 113 | // where file is the basename of szFile, ext is its extension |
| 114 | // or .conf (Unix) or .ini (Win) if it has none |
| 115 | static wxFileName GetGlobalFile(const wxString& szFile); |
| 116 | static wxFileName GetLocalFile(const wxString& szFile, int style = 0); |
| 117 | |
| 118 | static wxString GetGlobalFileName(const wxString& szFile) |
| 119 | { |
| 120 | return GetGlobalFile(szFile).GetFullPath(); |
| 121 | } |
| 122 | |
| 123 | static wxString GetLocalFileName(const wxString& szFile, int style = 0) |
| 124 | { |
| 125 | return GetLocalFile(szFile, style).GetFullPath(); |
| 126 | } |
| 127 | |
| 128 | // ctor & dtor |
| 129 | // New constructor: one size fits all. Specify wxCONFIG_USE_LOCAL_FILE or |
| 130 | // wxCONFIG_USE_GLOBAL_FILE to say which files should be used. |
| 131 | wxFileConfig(const wxString& appName = wxEmptyString, |
| 132 | const wxString& vendorName = wxEmptyString, |
| 133 | const wxString& localFilename = wxEmptyString, |
| 134 | const wxString& globalFilename = wxEmptyString, |
| 135 | long style = wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_GLOBAL_FILE, |
| 136 | const wxMBConv& conv = wxConvAuto()); |
| 137 | |
| 138 | #if wxUSE_STREAMS |
| 139 | // ctor that takes an input stream. |
| 140 | wxFileConfig(wxInputStream &inStream, const wxMBConv& conv = wxConvAuto()); |
| 141 | #endif // wxUSE_STREAMS |
| 142 | |
| 143 | // dtor will save unsaved data |
| 144 | virtual ~wxFileConfig(); |
| 145 | |
| 146 | // under Unix, set the umask to be used for the file creation, do nothing |
| 147 | // under other systems |
| 148 | #ifdef __UNIX__ |
| 149 | void SetUmask(int mode) { m_umask = mode; } |
| 150 | #else // !__UNIX__ |
| 151 | void SetUmask(int WXUNUSED(mode)) { } |
| 152 | #endif // __UNIX__/!__UNIX__ |
| 153 | |
| 154 | // implement inherited pure virtual functions |
| 155 | virtual void SetPath(const wxString& strPath); |
| 156 | virtual const wxString& GetPath() const; |
| 157 | |
| 158 | virtual bool GetFirstGroup(wxString& str, long& lIndex) const; |
| 159 | virtual bool GetNextGroup (wxString& str, long& lIndex) const; |
| 160 | virtual bool GetFirstEntry(wxString& str, long& lIndex) const; |
| 161 | virtual bool GetNextEntry (wxString& str, long& lIndex) const; |
| 162 | |
| 163 | virtual size_t GetNumberOfEntries(bool bRecursive = false) const; |
| 164 | virtual size_t GetNumberOfGroups(bool bRecursive = false) const; |
| 165 | |
| 166 | virtual bool HasGroup(const wxString& strName) const; |
| 167 | virtual bool HasEntry(const wxString& strName) const; |
| 168 | |
| 169 | virtual bool Flush(bool bCurrentOnly = false); |
| 170 | |
| 171 | virtual bool RenameEntry(const wxString& oldName, const wxString& newName); |
| 172 | virtual bool RenameGroup(const wxString& oldName, const wxString& newName); |
| 173 | |
| 174 | virtual bool DeleteEntry(const wxString& key, bool bGroupIfEmptyAlso = true); |
| 175 | virtual bool DeleteGroup(const wxString& szKey); |
| 176 | virtual bool DeleteAll(); |
| 177 | |
| 178 | // additional, wxFileConfig-specific, functionality |
| 179 | #if wxUSE_STREAMS |
| 180 | // save the entire config file text to the given stream, note that the text |
| 181 | // won't be saved again in dtor when Flush() is called if you use this method |
| 182 | // as it won't be "changed" any more |
| 183 | virtual bool Save(wxOutputStream& os, const wxMBConv& conv = wxConvAuto()); |
| 184 | #endif // wxUSE_STREAMS |
| 185 | |
| 186 | public: |
| 187 | // functions to work with this list |
| 188 | wxFileConfigLineList *LineListAppend(const wxString& str); |
| 189 | wxFileConfigLineList *LineListInsert(const wxString& str, |
| 190 | wxFileConfigLineList *pLine); // NULL => Prepend() |
| 191 | void LineListRemove(wxFileConfigLineList *pLine); |
| 192 | bool LineListIsEmpty(); |
| 193 | |
| 194 | protected: |
| 195 | virtual bool DoReadString(const wxString& key, wxString *pStr) const; |
| 196 | virtual bool DoReadLong(const wxString& key, long *pl) const; |
| 197 | #if wxUSE_BASE64 |
| 198 | virtual bool DoReadBinary(const wxString& key, wxMemoryBuffer* buf) const; |
| 199 | #endif // wxUSE_BASE64 |
| 200 | |
| 201 | virtual bool DoWriteString(const wxString& key, const wxString& szValue); |
| 202 | virtual bool DoWriteLong(const wxString& key, long lValue); |
| 203 | #if wxUSE_BASE64 |
| 204 | virtual bool DoWriteBinary(const wxString& key, const wxMemoryBuffer& buf); |
| 205 | #endif // wxUSE_BASE64 |
| 206 | |
| 207 | private: |
| 208 | // GetXXXFileName helpers: return ('/' terminated) directory names |
| 209 | static wxString GetGlobalDir(); |
| 210 | static wxString GetLocalDir(int style = 0); |
| 211 | |
| 212 | // common part of all ctors (assumes that m_str{Local|Global}File are already |
| 213 | // initialized |
| 214 | void Init(); |
| 215 | |
| 216 | // common part of from dtor and DeleteAll |
| 217 | void CleanUp(); |
| 218 | |
| 219 | // parse the whole file |
| 220 | void Parse(const wxTextBuffer& buffer, bool bLocal); |
| 221 | |
| 222 | // the same as SetPath("/") |
| 223 | void SetRootPath(); |
| 224 | |
| 225 | // real SetPath() implementation, returns true if path could be set or false |
| 226 | // if path doesn't exist and createMissingComponents == false |
| 227 | bool DoSetPath(const wxString& strPath, bool createMissingComponents); |
| 228 | |
| 229 | // set/test the dirty flag |
| 230 | void SetDirty() { m_isDirty = true; } |
| 231 | void ResetDirty() { m_isDirty = false; } |
| 232 | bool IsDirty() const { return m_isDirty; } |
| 233 | |
| 234 | |
| 235 | // member variables |
| 236 | // ---------------- |
| 237 | wxFileConfigLineList *m_linesHead, // head of the linked list |
| 238 | *m_linesTail; // tail |
| 239 | |
| 240 | wxFileName m_fnLocalFile, // local file name passed to ctor |
| 241 | m_fnGlobalFile; // global |
| 242 | wxString m_strPath; // current path (not '/' terminated) |
| 243 | |
| 244 | wxFileConfigGroup *m_pRootGroup, // the top (unnamed) group |
| 245 | *m_pCurrentGroup; // the current group |
| 246 | |
| 247 | wxMBConv *m_conv; |
| 248 | |
| 249 | #ifdef __UNIX__ |
| 250 | int m_umask; // the umask to use for file creation |
| 251 | #endif // __UNIX__ |
| 252 | |
| 253 | bool m_isDirty; // if true, we have unsaved changes |
| 254 | |
| 255 | wxDECLARE_NO_COPY_CLASS(wxFileConfig); |
| 256 | DECLARE_ABSTRACT_CLASS(wxFileConfig) |
| 257 | }; |
| 258 | |
| 259 | #endif |
| 260 | // wxUSE_CONFIG |
| 261 | |
| 262 | #endif |
| 263 | //_FILECONF_H |
| 264 | |