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