1 //
2 // "$Id: Fl_Preferences.H 7949 2010-12-05 00:38:16Z greg.ercolano $"
3 //
4 // Preferences .
5 //
6 // Copyright 2002-2010 by Matthias Melcher.
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 // Library General Public License for more details.
17 //
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 // USA.
22 //
23 // Please report all bugs and problems on the following page:
24 //
25 //     http://www.fltk.org/str.php
26 //
27 
28 /* \file
29    Fl_Preferences class . */
30 
31 #ifndef Fl_Preferences_H
32 #  define Fl_Preferences_H
33 
34 #  include <stdio.h>
35 #  include "Fl_Export.H"
36 
37 /**
38    \brief Fl_Preferences provides methods to store user
39    settings between application starts.
40 
41    It is similar to the
42    Registry on WIN32 and Preferences on MacOS, and provides a
43    simple configuration mechanism for UNIX.
44 
45    Fl_Preferences uses a hierarchy to store data. It
46    bundles similar data into groups and manages entries into those
47    groups as name/value pairs.
48 
49    Preferences are stored in text files that can be edited
50    manually. The file format is easy to read and relatively
51    forgiving. Preferences files are the same on all platforms. User
52    comments in preference files are preserved. Filenames are unique
53    for each application by using a vendor/application naming
54    scheme. The user must provide default values for all entries to
55    ensure proper operation should preferences be corrupted or not
56    yet exist.
57 
58    Entries can be of any length. However, the size of each
59    preferences file should be kept small for performance
60    reasons. One application can have multiple preferences files.
61    Extensive binary data however should be stored in separate
62    files: see getUserdataPath().
63 
64    \note Starting with FLTK 1.3, preference databases are expected to
65    be in utf8 encoding. Previous databases were stored in the
66    current chracter set or code page which renders them incompatible
67    for text entries using international characters.
68  */
69 class FL_EXPORT Fl_Preferences {
70 
71 public:
72   /**
73      Define the scope of the preferences.
74    */
75   enum Root {
76     SYSTEM=0,   ///< Preferences are used system-wide
77     USER        ///< Preferences apply only to the current user
78   };
79 
80   /**
81    Every Fl_Preferences-Group has a uniqe ID.
82 
83    ID's can be retrieved from an Fl_Preferences-Group and can then be used
84    to create more Fl_Preference references to the same data set, as long as the
85    database remains open.
86    */
87   typedef void *ID;
88 
89   static const char *newUUID();
90 
91   Fl_Preferences( Root root, const char *vendor, const char *application );
92   Fl_Preferences( const char *path, const char *vendor, const char *application );
93   Fl_Preferences( Fl_Preferences &parent, const char *group );
94   Fl_Preferences( Fl_Preferences *parent, const char *group );
95   Fl_Preferences( Fl_Preferences &parent, int groupIndex );
96   Fl_Preferences( Fl_Preferences *parent, int groupIndex );
97   Fl_Preferences(const Fl_Preferences&);
98   Fl_Preferences( ID id );
99   virtual ~Fl_Preferences();
100 
101   /** Return an ID that can later be reused to open more references to this dataset.
102    */
id()103   ID id() { return (ID)node; }
104 
105   /** Remove the group with this ID from a database.
106    */
remove(ID id_)107   static char remove(ID id_) { return ((Node*)id_)->remove(); }
108 
109   /** Return the name of this entry.
110    */
name()111   const char *name() { return node->name(); }
112 
113   /** Return the the full path to this entry.
114    */
path()115   const char *path() { return node->path(); }
116 
117   int groups();
118   const char *group( int num_group );
119   char groupExists( const char *key );
120   char deleteGroup( const char *group );
121   char deleteAllGroups();
122 
123   int entries();
124   const char *entry( int index );
125   char entryExists( const char *key );
126   char deleteEntry( const char *entry );
127   char deleteAllEntries();
128 
129   char clear();
130 
131   char set( const char *entry, int value );
132   char set( const char *entry, float value );
133   char set( const char *entry, float value, int precision );
134   char set( const char *entry, double value );
135   char set( const char *entry, double value, int precision );
136   char set( const char *entry, const char *value );
137   char set( const char *entry, const void *value, int size );
138 
139   char get( const char *entry, int &value, int defaultValue );
140   char get( const char *entry, float &value,  float defaultValue );
141   char get( const char *entry, double &value, double defaultValue );
142   char get( const char *entry, char *&value,  const char *defaultValue );
143   char get( const char *entry, char *value,   const char *defaultValue, int maxSize );
144   char get( const char *entry, void *&value,  const void *defaultValue, int defaultSize );
145   char get( const char *entry, void *value,   const void *defaultValue, int defaultSize, int maxSize );
146 
147   int size( const char *entry );
148 
149   char getUserdataPath( char *path, int pathlen );
150 
151   void flush();
152 
153   // char export( const char *filename, Type fileFormat );
154   // char import( const char *filename );
155 
156   /**
157      'Name' provides a simple method to create numerical or more complex
158      procedural names for entries and groups on the fly.
159 
160      Example: prefs.set(Fl_Preferences::Name("File%d",i),file[i]);.
161 
162      See test/preferences.cxx as a sample for writing arrays into preferences.<p>
163      'Name' is actually implemented as a class inside Fl_Preferences. It casts
164      into const char* and gets automatically destroyed after the enclosing call
165      ends.
166    */
167   class FL_EXPORT Name {
168 
169     char *data_;
170 
171   public:
172     Name( unsigned int n );
173     Name( const char *format, ... );
174 
175     /**
176        Return the Name as a "C" string.
177        \internal
178      */
179     operator const char *() { return data_; }
180     ~Name();
181   };
182 
183   /** \internal An entry associates a preference name to its corresponding value */
184   struct Entry {
185     char *name, *value;
186   };
187 
188 private:
Fl_Preferences()189   Fl_Preferences() : node(0), rootNode(0) { }
190   Fl_Preferences &operator=(const Fl_Preferences&);
191 
192   static char nameBuffer[128];
193   static char uuidBuffer[40];
194   static Fl_Preferences *runtimePrefs;
195 
196   class RootNode;
197 
198   class FL_EXPORT Node {	// a node contains a list to all its entries
199             			// and all means to manage the tree structure
200     Node *child_, *next_;
201     union { 			// these two are mutually exclusive
202       Node *parent_;   		// top_ bit clear
203       RootNode *root_; 		// top_ bit set
204     };
205     char *path_;
206     Entry *entry_;
207     int nEntry_, NEntry_;
208     unsigned char dirty_:1;
209     unsigned char top_:1;
210     unsigned char indexed_:1;
211     // indexing routines
212     Node **index_;
213     int nIndex_, NIndex_;
214     void createIndex();
215     void updateIndex();
216     void deleteIndex();
217   public:
218     static int lastEntrySet;
219   public:
220     Node( const char *path );
221     ~Node();
222     // node methods
223     int write( FILE *f );
224     const char *name();
path()225     const char *path() { return path_; }
226     Node *find( const char *path );
227     Node *search( const char *path, int offset=0 );
228     Node *childNode( int ix );
229     Node *addChild( const char *path );
230     void setParent( Node *parent );
parent()231     Node *parent() { return top_?0L:parent_; }
setRoot(RootNode * r)232     void setRoot(RootNode *r) { root_ = r; top_ = 1; }
233     RootNode *findRoot();
234     char remove();
235     char dirty();
236     void deleteAllChildren();
237     // entry methods
238     int nChildren();
239     const char *child( int ix );
240     void set( const char *name, const char *value );
241     void set( const char *line );
242     void add( const char *line );
243     const char *get( const char *name );
244     int getEntry( const char *name );
245     char deleteEntry( const char *name );
246     void deleteAllEntries();
nEntry()247     int nEntry() { return nEntry_; }
entry(int i)248     Entry &entry(int i) { return entry_[i]; }
249   };
250   friend class Node;
251 
252   class FL_EXPORT RootNode {		// the root node manages file paths and basic reading and writing
253     Fl_Preferences *prefs_;
254     char *filename_;
255     char *vendor_, *application_;
256   public:
257     RootNode( Fl_Preferences *, Root root, const char *vendor, const char *application );
258     RootNode( Fl_Preferences *, const char *path, const char *vendor, const char *application );
259     RootNode( Fl_Preferences * );
260     ~RootNode();
261     int read();
262     int write();
263     char getPath( char *path, int pathlen );
264   };
265   friend class RootNode;
266 
267 protected:
268   Node *node;
269   RootNode *rootNode;
270 };
271 
272 #endif // !Fl_Preferences_H
273 
274 //
275 // End of "$Id: Fl_Preferences.H 7949 2010-12-05 00:38:16Z greg.ercolano $".
276 //
277