summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FL/Fl_Preferences.H18
-rw-r--r--src/Fl_Preferences.cxx146
2 files changed, 156 insertions, 8 deletions
diff --git a/FL/Fl_Preferences.H b/FL/Fl_Preferences.H
index eba771aee..7ad5de756 100644
--- a/FL/Fl_Preferences.H
+++ b/FL/Fl_Preferences.H
@@ -79,13 +79,25 @@ public:
SYSTEM=0, ///< Preferences are used system-wide
USER ///< Preferences apply only to the current user
};
+
+ static const char *newUUID();
Fl_Preferences( Root root, const char *vendor, const char *application );
Fl_Preferences( const char *path, const char *vendor, const char *application );
Fl_Preferences( Fl_Preferences &parent, const char *group );
- Fl_Preferences( Fl_Preferences*, const char *group );
+ Fl_Preferences( Fl_Preferences *parent, const char *group );
+ Fl_Preferences( Fl_Preferences &parent, int groupIndex );
+ Fl_Preferences( Fl_Preferences *parent, int groupIndex );
~Fl_Preferences();
+ /** Return the name of this entry.
+ */
+ const char *name() { return node->name(); }
+
+ /** Return the the full path to this entry.
+ */
+ const char *path() { return node->path(); }
+
int groups();
const char *group( int num_group );
char groupExists( const char *key );
@@ -163,6 +175,7 @@ private:
Fl_Preferences &operator=(const Fl_Preferences&);
static char nameBuffer[128];
+ static char uuidBuffer[40];
class FL_EXPORT Node // a node contains a list to all its entries
{ // and all means to manage the tree structure
@@ -174,6 +187,8 @@ private:
~Node();
// node methods
int write( FILE *f );
+ const char *name();
+ const char *path() { return path_; }
Node *find( const char *path );
Node *search( const char *path, int offset=0 );
Node *addChild( const char *path );
@@ -184,6 +199,7 @@ private:
// entry methods
int nChildren();
const char *child( int ix );
+ Node *childNode( int ix );
void set( const char *name, const char *value );
void set( const char *line );
void add( const char *line );
diff --git a/src/Fl_Preferences.cxx b/src/Fl_Preferences.cxx
index a24cf85d5..866c90cae 100644
--- a/src/Fl_Preferences.cxx
+++ b/src/Fl_Preferences.cxx
@@ -36,6 +36,7 @@
#include <FL/fl_utf8.h>
#include "flstring.h"
#include <sys/stat.h>
+#include <time.h>
#if defined(WIN32) && !defined(__CYGWIN__)
# include <direct.h>
@@ -52,10 +53,88 @@
#endif
#ifdef WIN32
-#include <windows.h>
+# include <windows.h>
+#else
+# include <sys/time.h>
#endif // WIN32
char Fl_Preferences::nameBuffer[128];
+char Fl_Preferences::uuidBuffer[40];
+
+/**
+ * Returns a UUID as generated by the system.
+ *
+ * A UUID is a "universally unique identifier" which is commonly used in
+ * configuration files to create identities. A UUID in ASCII looks like this:
+ * <tt>937C4900-51AA-4C11-8DD3-7AB59944F03E</tt>. It has always 36 bytes plus
+ * a trailing zero.
+ *
+ * \return a pointer to a static buffer containing the new UUID in ASCII format.
+ * The buffer is overwritten during every call to this function!
+ */
+const char *Fl_Preferences::newUUID()
+{
+#ifdef __APPLE__
+ CFUUIDRef theUUID = CFUUIDCreate(NULL);
+ CFUUIDBytes b = CFUUIDGetUUIDBytes(theUUID);
+ sprintf(uuidBuffer, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ b.byte0, b.byte1, b.byte2, b.byte3, b.byte4, b.byte5, b.byte6, b.byte7,
+ b.byte8, b.byte9, b.byte10, b.byte11, b.byte12, b.byte13, b.byte14, b.byte15);
+ CFRelease(theUUID);
+#elif defined (WIN32)
+#warning MSWindows implementation missing!
+ // UUID b;
+ // UuidCreate(&b);
+ unsigned char b[16];
+ time_t t = time(0); // first 4 byte
+ b[0] = (unsigned char)t;
+ b[1] = (unsigned char)(t>>8);
+ b[2] = (unsigned char)(t>>16);
+ b[3] = (unsigned char)(t>>24);
+ int r = rand(); // four more bytes
+ b[4] = (unsigned char)r;
+ b[5] = (unsigned char)(r>>8);
+ b[6] = (unsigned char)(r>>16);
+ b[7] = (unsigned char)(r>>24);
+ unsigned int a = (unsigned int)&t; // four more bytes
+ b[8] = (unsigned char)a;
+ b[9] = (unsigned char)(a>>8);
+ b[10] = (unsigned char)(a>>16);
+ b[11] = (unsigned char)(a>>24);
+ char name[80]; // last four bytes
+ gethostname(name, 79);
+ memcpy(b+12, name, 4);
+ sprintf(uuidBuffer, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
+ b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]);
+#else
+#warning Unix implementation missing!
+ // #include <uuid/uuid.h>
+ // void uuid_generate(uuid_t out);
+ unsigned char b[16];
+ time_t t = time(0); // first 4 byte
+ b[0] = (unsigned char)t;
+ b[1] = (unsigned char)(t>>8);
+ b[2] = (unsigned char)(t>>16);
+ b[3] = (unsigned char)(t>>24);
+ int r = rand(); // four more bytes
+ b[4] = (unsigned char)r;
+ b[5] = (unsigned char)(r>>8);
+ b[6] = (unsigned char)(r>>16);
+ b[7] = (unsigned char)(r>>24);
+ unsigned int a = (unsigned int)&t; // four more bytes
+ b[8] = (unsigned char)a;
+ b[9] = (unsigned char)(a>>8);
+ b[10] = (unsigned char)(a>>16);
+ b[11] = (unsigned char)(a>>24);
+ char name[80]; // last four bytes
+ gethostname(name, 79);
+ memcpy(b+12, name, 4);
+ sprintf(uuidBuffer, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
+ b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]);
+#endif
+}
/**
@@ -133,6 +212,41 @@ Fl_Preferences::Fl_Preferences( Fl_Preferences *parent, const char *group )
/**
+ \brief Open a child group using a given index.
+
+ Use the \p groupIndex argument to find the group that you would like to access.
+ If the given index is invalid (negative or too high), a new group is created
+ with a UUID as a name.
+
+ \param[in] parent reference object for the new group
+ \param[in] groupIndex zero based index into child groups
+ */
+Fl_Preferences::Fl_Preferences( Fl_Preferences &parent, int groupIndex )
+{
+ rootNode = parent.rootNode;
+ if (groupIndex<0 || groupIndex>=parent.groups()) {
+ node = parent.node->addChild( newUUID() );
+ } else {
+ node = parent.node->childNode( groupIndex );
+ }
+}
+
+
+/**
+ \see Fl_Preferences( Fl_Preferences&, int groupIndex )
+ */
+Fl_Preferences::Fl_Preferences( Fl_Preferences *parent, int groupIndex )
+{
+ rootNode = parent->rootNode;
+ if (groupIndex<0 || groupIndex>=parent->groups()) {
+ node = parent->node->addChild( newUUID() );
+ } else {
+ node = parent->node->childNode( groupIndex );
+ }
+}
+
+
+/**
The destructor removes allocated resources. When used on the
\em base preferences group, the destructor flushes all
changes to the preferences file and deletes all internal
@@ -1348,20 +1462,38 @@ int Fl_Preferences::Node::nChildren()
return cnt;
}
+// return the node name
+const char *Fl_Preferences::Node::name()
+{
+ if ( path_ )
+ {
+ char *r = strrchr( path_, '/' );
+ return r ? r+1 : path_ ;
+ } else {
+ return 0L ;
+ }
+}
+
// return the n'th child node
const char *Fl_Preferences::Node::child( int ix )
{
+ Node *nd = childNode( ix );
+ if ( nd )
+ return nd->name();
+ else
+ return 0L ;
+}
+
+// return the n'th child node
+Fl_Preferences::Node *Fl_Preferences::Node::childNode( int ix )
+{
Node *nd;
for ( nd = child_; nd; nd = nd->next_ )
{
if ( !ix-- ) break;
+ if ( !nd ) break;
}
- if ( nd && nd->path_ )
- {
- char *r = strrchr( nd->path_, '/' );
- return r ? r+1 : nd->path_ ;
- }
- return 0L ;
+ return nd;
}
// remove myself from the list and delete me (and all children)