summaryrefslogtreecommitdiff
path: root/src/Fl_Preferences.cxx
diff options
context:
space:
mode:
authorMatthias Melcher <github@matthiasm.com>2022-01-19 16:08:29 +0100
committerGitHub <noreply@github.com>2022-01-19 16:08:29 +0100
commit09eff7243a6e8e37d9615df7b951ffa3c03c0ae2 (patch)
tree513b39c92f1f6a9d0f0ca7f9a1488f298f7a068e /src/Fl_Preferences.cxx
parent793f4b90fac349b096922a6b90ae2731777ac6cf (diff)
Fixing and upgrading Fl_Preferences (#374)
* Added filename function to Fl_Preferences Static function to get filename before opening. Member to get filename after opening. Bug fixes for memory mapped preferences. * ERROR is a macro on Windows, don't use it * Added Fl_Preferences::dirty(). User can now check if the database will be written when flushed or destroyed. Flush returns a crude error code. * Fl_Preferences::get binary data returns # of bytes read. * Verified group deletion code * Fl_Preferences ignores locale. This will make .prefs files interchangeable between different computers. * Updating the Preferences Mode to ignore locale. * Fixes in docs.
Diffstat (limited to 'src/Fl_Preferences.cxx')
-rw-r--r--src/Fl_Preferences.cxx467
1 files changed, 340 insertions, 127 deletions
diff --git a/src/Fl_Preferences.cxx b/src/Fl_Preferences.cxx
index 0ac1c17ea..83fa3da99 100644
--- a/src/Fl_Preferences.cxx
+++ b/src/Fl_Preferences.cxx
@@ -1,7 +1,7 @@
//
// Preferences methods for the Fast Light Tool Kit (FLTK).
//
-// Copyright 2011-2020 by Bill Spitzak and others.
+// Copyright 2011-2022 by Bill Spitzak and others.
// Copyright 2002-2010 by Matthias Melcher.
//
// This library is free software. Distribution and use rights are outlined in
@@ -34,6 +34,24 @@ char Fl_Preferences::uuidBuffer[40];
Fl_Preferences *Fl_Preferences::runtimePrefs = 0;
unsigned int Fl_Preferences::fileAccess_ = Fl_Preferences::ALL;
+static int clocale_snprintf(char *buffer, size_t buffer_size, const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ int retval = Fl::system_driver()->clocale_snprintf(buffer, buffer_size, format, args);
+ va_end(args);
+ return retval;
+}
+
+static int clocale_sscanf(const char *input, const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ int retval = Fl::system_driver()->clocale_sscanf(input, format, args);
+ va_end(args);
+ return retval;
+}
+
/**
Returns a UUID as generated by the system.
@@ -101,68 +119,108 @@ unsigned int Fl_Preferences::file_access()
}
/**
+ Determine the file name and path to preferences that would be openend with
+ these parameters.
+
+ Find the possible location of a preference file on disk without touching any
+ of the pathname componennts. This can be used to check if a preferneces file
+ already exists.
+
+ \param[out] buffer write the reulting path into this buffer
+ \param[in] buffer_size size of the `buffer` in bytes
+ \param[in] root can be \c USER_L or \c SYSTEM_L for user specific or system
+ wide preferences
+ \param[in] vendor unique text describing the company or author of this file,
+ must be a valid filepath segment
+ \param[in] application unique text describing the application, must be a
+ valid filepath segment
+ \return the input root value, or Fl_Preferences::UNKNOWN_ROOT_TYPE if the path
+ could not be determined.
+ \see Fl_Preferences( Root root, const char *vendor, const char *application )
+ */
+Fl_Preferences::Root Fl_Preferences::filename( char *buffer, size_t buffer_size, Root root, const char *vendor, const char *application )
+{
+ Root ret = UNKNOWN_ROOT_TYPE;
+ if (buffer && buffer_size>0) {
+ char *fn = Fl::system_driver()->preference_rootnode(NULL, root, vendor, application);
+ if (fn) {
+ fl_strlcpy(buffer, fn, buffer_size);
+ // FLTK always returns forward slashes in paths
+ { char *s; for ( s = buffer; *s; s++ ) if ( *s == '\\' ) *s = '/'; }
+ ret = root;
+ } else {
+ buffer[0] = 0;
+ }
+ }
+ return ret;
+}
+
+
+/**
The constructor creates a group that manages name/value pairs and
child groups. Groups are ready for reading and writing at any time.
- The root argument is either Fl_Preferences::USER
- or Fl_Preferences::SYSTEM.
-
- This constructor creates the <i>base</i> instance for all
- following entries and reads existing databases into memory. The
- vendor argument is a unique text string identifying the
- development team or vendor of an application. A domain name or
- an EMail address are great unique names, e.g.
- "research.matthiasm.com" or "fluid.fltk.org". The
- application argument can be the working title or final
- name of your application. Both vendor and
- application must be valid UNIX path segments and
- may contain forward slashes to create deeper file structures.
-
- A set of Preferences marked "run-time" exists exactly once per application and
- only as long as the application runs. It can be used as a database for
- volatile information. FLTK uses it to register plugins at run-time.
-
- \note On \b Windows, the directory is constructed by querying the <i>Common AppData</i>
- or <i>AppData</i> key of the <tt>Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders</tt>
- registry entry. The filename and path is then constructed as <tt>\$(query)/\$(vendor)/\$(application).prefs</tt> .
- If the query call fails, data will be stored in RAM only and be lost when the app exits.
-
- \par In FLTK versions before 1.4.0, if querying the registry failed, preferences would be written to
+ The root argument is either `Fl_Preferences::USER_L`
+ or `Fl_Preferences::SYSTEM_L`.
+
+ This constructor creates the <i>base</i> instance for all following entries
+ and reads the database from disk into memory if it exists.
+ The vendor argument is a unique text string identifying the development team
+ or vendor of an application. A domain name or an EMail address (replacing
+ the '@' with a '.') are great unique names, e.g. "research.matthiasm.com" or
+ "fluid.fltk.org".
+ The application argument can be the working title or final name of your
+ application.
+ Both vendor and application must be valid UNIX path segments as they become
+ parts of the preferences file path and may contain forward slashes to create
+ deeper file structures.
+
+ \note On \b Windows, the directory is constructed by querying the
+ <i>Common AppData</i> or <i>AppData</i> key of the
+ <tt>Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders</tt>
+ registry entry.
+ The filename and path is then constructed as
+ <tt>\$(query)/\$(vendor)/\$(application).prefs</tt> .
+ If the query call fails, data will be stored in RAM only.
+ It will be lost when the app exits.
+
+ \par In FLTK versions before 1.4.0, if querying the registry failed,
+ preferences would be written to
<tt>C:\\FLTK\\\$(vendor)\\\$(application).prefs</tt> .
- \note On \b Linux, the \c USER directory is constructed by reading \c $HOME . If \c $HOME is not set
- or not pointing to an existing directory, we are checking the path member of the passwd struct returned by
- \c getpwuid(getuid()) . If all attempts fail, data will be stored in RAM only and be lost when the app exits.
- The filename and path is then constructed as <tt>\$(directory)/.fltk/\$(vendor)/\$(application).prefs</tt> .
- The \c SYSTEM directory is hardcoded as <tt>/etc/fltk/\$(vendor)/\$(application).prefs</tt> .
-
- \par In FLTK versions before 1.4.0, if \c $HOME was not set, the \c USER path would be empty,
- generating <tt>\$(vendor)/\$(application).prefs</tt>, which was used relative to the current working directory.
-
- \note On \b macOS, the \c USER directory is constructed by reading \c $HOME . If \c $HOME is not set
- or not pointing to an existing directory, we check the path returned by \c NSHomeDirectory() , and
- finally checking the path member of the passwd struct returned by \c getpwuid(getuid()) .
+ \note On \b Linux, the \c USER directory is constructed by reading \c $HOME .
+ If \c $HOME is not set or not pointing to an existing directory, FLTK will
+ check the path member of the passwd struct returned by \c getpwuid(getuid()) .
+ If all attempts fail, data will be stored in RAM only and be lost when the
+ app exits.
+ The filename and path is then constructed as
+ <tt>\$(directory)/.fltk/\$(vendor)/\$(application).prefs</tt> .
+ The \c SYSTEM directory is hardcoded as
+ <tt>/etc/fltk/\$(vendor)/\$(application).prefs</tt> .
+
+ \par In FLTK versions before 1.4.0, if \c $HOME was not set, the \c USER path
+ would be empty, generating <tt>\$(vendor)/\$(application).prefs</tt>, which
+ was used relative to the current working directory.
+
+ \note On \b macOS, the \c USER directory is constructed by reading \c $HOME .
+ If \c $HOME is not set or not pointing to an existing directory, we check the
+ path returned by \c NSHomeDirectory() , and finally checking the path member
+ of the passwd struct returned by \c getpwuid(getuid()) .
If all attempts fail, data will be stored in RAM only and be lost when the app exits.
- The filename and path is then constructed as <tt>\$(directory)/Library/Preferences/\$(vendor)/\$(application).prefs</tt> .
- The \c SYSTEM directory is hardcoded as <tt>/Library/Preferences/\$(vendor)/\$(application).prefs</tt> .
+ The filename and path is then constructed as
+ <tt>\$(directory)/Library/Preferences/\$(vendor)/\$(application).prefs</tt> .
+ The \c SYSTEM directory is hardcoded as
+ <tt>/Library/Preferences/\$(vendor)/\$(application).prefs</tt> .
- \par In FLTK versions before 1.4.0, if \c $HOME was not set, the \c USER path would be \c NULL ,
- generating <tt>\<null\>/Library/Preferences/\$(vendor)/\$(application).prefs</tt>, which would silently fail to
- create a preferences file.
+ \par In FLTK versions before 1.4.0, if \c $HOME was not set, the \c USER path
+ would be \c NULL , generating
+ <tt>\<null\>/Library/Preferences/\$(vendor)/\$(application).prefs</tt>,
+ which would silently fail to create a preferences file.
- \param[in] root can be \c USER or \c SYSTEM for user specific or system wide preferences
+ \param[in] root can be \c USER_L or \c SYSTEM_L for user specific or system wide preferences
\param[in] vendor unique text describing the company or author of this file, must be a valid filepath segment
\param[in] application unique text describing the application, must be a valid filepath segment
- \todo (Matt) Before the release of 1.4.0, I want to make a further attempt to write a preferences file smarter. I
- plan to use a subgroup of the "runtime" preferences to store data and stay accessible until the application
- exits. Data would be stored under <tt>./\$(vendor)/\$(application).prefs</tt> in RAM, but not on disk.
-
- \todo (Matt) I want a way to access the type of the root preferences (SYSTEM, USER, MEMORY), and the state of
- the file access (OK, FILE_SYSTEM_FAIL, PERMISSION_FAIL, etc.), and probably the dirty() flag as well.
-
- \todo (Matt) Also, I need to explain runtime preferences.
-
- \todo (Matt) Lastly, I think I have to put short sample code in the Doxygen docs. The test app ist just not enough.
+ \see Fl_Preferences(Fl_Preferences *parent, const char *group) with parent set to NULL
*/
Fl_Preferences::Fl_Preferences( Root root, const char *vendor, const char *application ) {
node = new Node( "." );
@@ -203,22 +261,49 @@ Fl_Preferences::Fl_Preferences( Fl_Preferences &parent, const char *group ) {
}
/**
- \brief Create or access a group of preferences using a name.
+ \brief Create or access a group of preferences using a name.
+
+ Parent should point to a previously created parent preferences group to
+ create a preferences hierarchy.
+
+ If `parent` is set to `NULL`, an unnamed database will be accessed that exists
+ only in local memory and is not associated with a file on disk. The root type
+ of this databse is set to `Fl_Preferences::MEMORY`.
+
+ * the memory database is \em not shared among multiple instances of the same app
+ * memory databses are \em not thread safe
+ * all data will be lost when the app quits
+
+ ```{.cpp}
+ void some_function() {
+ Fl_Preferences guide( NULL, "Guide" );
+ guide.set("answer", 42);
+ }
+ void other_function() {
+ int x;
+ Fl_Preferences guide( NULL, "Guide" );
+ guide.get("answer", x, -1);
+ }
+ ```
+
+ FLTK uses the memory database to manage plugins. See `Fl_Plugin`.
+
\param[in] parent the parameter parent is a pointer to the parent group.
- \p Parent may be \p NULL. It then refers to an application internal
- database which exists only once, and remains in RAM only until the
- application quits. This database is used to manage plugins and other
- data indexes by strings.
+ If \p Parent is \p NULL, the new Preferences item refers to an
+ application internal database ("runtime prefs") which exists only
+ once, and remains in RAM only until the application quits.
+ This database is used to manage plugins and other data indexes
+ by strings. Runtime Prefs are \em not thread-safe.
\param[in] group a group name that is used as a key into the database
\see Fl_Preferences( Fl_Preferences&, const char *group )
*/
Fl_Preferences::Fl_Preferences( Fl_Preferences *parent, const char *group ) {
- if (parent==0) {
+ if (parent==NULL) {
if (!runtimePrefs) {
runtimePrefs = new Fl_Preferences();
runtimePrefs->node = new Node( "." );
runtimePrefs->rootNode = new RootNode( runtimePrefs );
- runtimePrefs->node->setRoot(rootNode);
+ runtimePrefs->node->setRoot(runtimePrefs->rootNode);
}
parent = runtimePrefs;
}
@@ -314,6 +399,35 @@ Fl_Preferences::~Fl_Preferences() {
}
/**
+ Return the file name and path to the Preferences file.
+
+ If the preferences have not changed or have not been flushed, the file
+ or directory may not have been created yet.
+
+ \param[out] buffer write the reulting path into this buffer
+ \param[in] buffer_size size of the `buffer` in bytes
+ \return the root type at creation type, or MEMORY for runtime prefs, it does
+ not return CORE or LOCALE flags.
+ */
+Fl_Preferences::Root Fl_Preferences::filename( char *buffer, size_t buffer_size)
+{
+ if (!buffer || buffer_size==0)
+ return UNKNOWN_ROOT_TYPE;
+ RootNode *rn = rootNode;
+ if (!rn)
+ return UNKNOWN_ROOT_TYPE;
+ if (rn->root()==MEMORY)
+ return MEMORY;
+ char *fn = rn->filename();
+ if (!fn)
+ return UNKNOWN_ROOT_TYPE;
+ fl_strlcpy(buffer, fn, buffer_size);
+ if (buffer[0]==0)
+ return UNKNOWN_ROOT_TYPE;
+ return (Root)(rn->root() & ROOT_MASK);
+}
+
+/**
Returns the number of groups that are contained within a group.
\return 0 for no groups at all
@@ -474,8 +588,16 @@ char Fl_Preferences::set( const char *key, int value ) {
*/
char Fl_Preferences::get( const char *key, float &value, float defaultValue ) {
const char *v = node->get( key );
- value = v ? (float)atof( v ) : defaultValue;
- return ( v != 0 );
+ if (v) {
+ if (rootNode->root() & C_LOCALE) {
+ clocale_sscanf(v, "%g", &value);
+ } else {
+ value = (float)atof(v);
+ }
+ } else {
+ value = defaultValue;
+ }
+ return ( v != NULL );
}
/**
@@ -489,7 +611,11 @@ char Fl_Preferences::get( const char *key, float &value, float defaultValue ) {
\return 0 if setting the value failed
*/
char Fl_Preferences::set( const char *key, float value ) {
- sprintf( nameBuffer, "%g", value );
+ if (rootNode->root() & C_LOCALE) {
+ clocale_snprintf( nameBuffer, sizeof(nameBuffer), "%g", value );
+ } else {
+ snprintf( nameBuffer, sizeof(nameBuffer), "%g", value );
+ }
node->set( key, nameBuffer );
return 1;
}
@@ -506,7 +632,11 @@ char Fl_Preferences::set( const char *key, float value ) {
\return 0 if setting the value failed
*/
char Fl_Preferences::set( const char *key, float value, int precision ) {
- sprintf( nameBuffer, "%.*g", precision, value );
+ if (rootNode->root() & C_LOCALE) {
+ clocale_snprintf( nameBuffer, sizeof(nameBuffer), "%.*g", precision, value );
+ } else {
+ snprintf( nameBuffer, sizeof(nameBuffer), "%.*g", precision, value );
+ }
node->set( key, nameBuffer );
return 1;
}
@@ -523,8 +653,16 @@ char Fl_Preferences::set( const char *key, float value, int precision ) {
*/
char Fl_Preferences::get( const char *key, double &value, double defaultValue ) {
const char *v = node->get( key );
- value = v ? atof( v ) : defaultValue;
- return ( v != 0 );
+ if (v) {
+ if (rootNode->root() & C_LOCALE) {
+ clocale_sscanf(v, "%lg", &value);
+ } else {
+ value = atof(v);
+ }
+ } else {
+ value = defaultValue;
+ }
+ return ( v != NULL );
}
/**
@@ -538,7 +676,11 @@ char Fl_Preferences::get( const char *key, double &value, double defaultValue )
\return 0 if setting the value failed
*/
char Fl_Preferences::set( const char *key, double value ) {
- sprintf( nameBuffer, "%g", value );
+ if (rootNode->root() & C_LOCALE) {
+ clocale_snprintf( nameBuffer, sizeof(nameBuffer), "%lg", value );
+ } else {
+ snprintf( nameBuffer, sizeof(nameBuffer), "%lg", value );
+ }
node->set( key, nameBuffer );
return 1;
}
@@ -555,7 +697,11 @@ char Fl_Preferences::set( const char *key, double value ) {
\return 0 if setting the value failed
*/
char Fl_Preferences::set( const char *key, double value, int precision ) {
- sprintf( nameBuffer, "%.*g", precision, value );
+ if (rootNode->root() & C_LOCALE) {
+ clocale_snprintf( nameBuffer, sizeof(nameBuffer), "%.*lg", precision, value );
+ } else {
+ snprintf( nameBuffer, sizeof(nameBuffer), "%.*lg", precision, value );
+ }
node->set( key, nameBuffer );
return 1;
}
@@ -695,19 +841,17 @@ static void *decodeHex( const char *src, int &size ) {
}
/**
- Reads an entry from the group. A default value must be
- supplied. The return value indicates if the value was available
- (non-zero) or the default was used (0).
- 'maxSize' is the maximum length of text that will be read.
+ Reads a binary entry from the group, ancoded in hexadecimal blocks.
\param[in] key name of entry
\param[out] data value returned from preferences or default value if none was set
- \param[in] defaultValue default value to be used if no preference was set
+ \param[in] defaultValue default value
\param[in] defaultSize size of default value array
- \param[in] maxSize maximum length of value
+ \param[in] maxSize maximum length of value, to receive the number of bytes
+ read, use the function below instead.
\return 0 if the default value was used
- \todo maxSize should receive the number of bytes that were read.
+ \see Fl_Preferences::get( const char *key, void *data, const void *defaultValue, int defaultSize, int *maxSize )
*/
char Fl_Preferences::get( const char *key, void *data, const void *defaultValue, int defaultSize, int maxSize ) {
const char *v = node->get( key );
@@ -724,6 +868,45 @@ char Fl_Preferences::get( const char *key, void *data, const void *defaultValue,
}
/**
+ Reads a binary entry from the group, ancoded in hexadecimal blocks.
+ A binary (not hex) default value can be supplied.
+ The return value indicates if the value was available (non-zero) or the
+ default was used (0).
+ `maxSize` is the maximum length of text that will be read and returns the
+ actual number of bytes read.
+
+ \param[in] key name of entry
+ \param[out] data value returned from preferences or default value if none was set
+ \param[in] defaultValue default value to be used if no preference was set
+ \param[in] defaultSize size of default value array
+ \param[inout] maxSize maximum length of value and actual number of bytes set
+ \return 0 if the default value was used
+ */
+char Fl_Preferences::get( const char *key, void *data, const void *defaultValue, int defaultSize, int *maxSize ) {
+ if (!maxSize || !data)
+ return -1;
+ int capacity = *maxSize;
+ const char *v = node->get( key );
+ if ( v ) {
+ int nFound;
+ void *w = decodeHex( v, nFound );
+ int nWrite = (nFound>capacity) ? capacity : nFound;
+ memmove( data, w, nWrite);
+ free( w );
+ *maxSize = nWrite;
+ return 1;
+ }
+ if ( defaultValue ) {
+ int nWrite = (defaultSize>capacity) ? capacity : defaultSize;
+ memmove( data, defaultValue, nWrite );
+ *maxSize = nWrite;
+ } else {
+ *maxSize = 0;
+ }
+ return 0;
+}
+
+/**
Reads an entry from the group. A default value must be
supplied. The return value indicates if the value was available
(non-zero) or the default was used (0). get() allocates memory of
@@ -836,13 +1019,40 @@ char Fl_Preferences::getUserdataPath( char *path, int pathlen ) {
}
/**
- Writes all preferences to disk. This function works only with
- the base preferences group. This function is rarely used as
- deleting the base preferences flushes automatically.
+ Writes preferences to disk if they were modified.
+
+ This method can be used to verify that writing a preferences file went well.
+ Deleting the base preferences object will also write the contents of the
+ database to disk.
+
+ \return -1 if anything went wrong, i.e. file could not be opened, permissions
+ blocked writing, etc.
+ \return 0 if the file was written to disk. This does not check if the disk ran
+ out of space and the file is truncated.
+ \return 1 if there no data written to the database and no write attempt
+ to disk was made.
*/
-void Fl_Preferences::flush() {
- if ( rootNode && node->dirty() )
- rootNode->write();
+int Fl_Preferences::flush() {
+ int ret = dirty();
+ if (ret!=1)
+ return ret;
+ return rootNode->write();
+}
+
+/**
+ Check if there were changes to the database that need to be written to disk.
+
+ \return 1 if the database will be written to disk by `flush` or destructor.
+ \return 0 if the databse is unchanged since the last write operation.
+ \return -1 f there is an internal database error.
+ */
+int Fl_Preferences::dirty() {
+ Node *n = node;
+ while (n && n->parent())
+ n = n->parent();
+ if (!n)
+ return -1;
+ return n->dirty();
}
//-----------------------------------------------------------------------------
@@ -909,7 +1119,7 @@ Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, Root root, const char
filename_(0L),
vendor_(0L),
application_(0L),
- root_(root)
+ root_type_(root)
{
char *filename = Fl::system_driver()->preference_rootnode(prefs, root, vendor, application);
filename_ = filename ? fl_strdup(filename) : 0L;
@@ -925,7 +1135,7 @@ Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, const char *path, con
filename_(0L),
vendor_(0L),
application_(0L),
- root_(Fl_Preferences::USER)
+ root_type_(Fl_Preferences::USER)
{
if (!vendor)
@@ -950,7 +1160,7 @@ Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs )
filename_(0L),
vendor_(0L),
application_(0L),
- root_(Fl_Preferences::USER)
+ root_type_(Fl_Preferences::MEMORY)
{
}
@@ -978,15 +1188,15 @@ Fl_Preferences::RootNode::~RootNode() {
int Fl_Preferences::RootNode::read() {
if (!filename_) // RUNTIME preferences, or filename could not be created
return -1;
- if ( (root_ & Fl_Preferences::CORE) && !(fileAccess_ & Fl_Preferences::CORE_READ_OK) ) {
+ if ( (root_type_ & Fl_Preferences::CORE) && !(fileAccess_ & Fl_Preferences::CORE_READ_OK) ) {
prefs_->node->clearDirtyFlags();
return -1;
}
- if ( ((root_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::USER) && !(fileAccess_ & Fl_Preferences::USER_READ_OK) ) {
+ if ( ((root_type_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::USER) && !(fileAccess_ & Fl_Preferences::USER_READ_OK) ) {
prefs_->node->clearDirtyFlags();
return -1;
}
- if ( ((root_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::SYSTEM) && !(fileAccess_ & Fl_Preferences::SYSTEM_READ_OK) ) {
+ if ( ((root_type_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::SYSTEM) && !(fileAccess_ & Fl_Preferences::SYSTEM_READ_OK) ) {
prefs_->node->clearDirtyFlags();
return -1;
}
@@ -1027,11 +1237,11 @@ int Fl_Preferences::RootNode::read() {
int Fl_Preferences::RootNode::write() {
if (!filename_) // RUNTIME preferences, or filename could not be created
return -1;
- if ( (root_ & Fl_Preferences::CORE) && !(fileAccess_ & Fl_Preferences::CORE_WRITE_OK) )
+ if ( (root_type_ & Fl_Preferences::CORE) && !(fileAccess_ & Fl_Preferences::CORE_WRITE_OK) )
return -1;
- if ( ((root_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::USER) && !(fileAccess_ & Fl_Preferences::USER_WRITE_OK) )
+ if ( ((root_type_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::USER) && !(fileAccess_ & Fl_Preferences::USER_WRITE_OK) )
return -1;
- if ( ((root_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::SYSTEM) && !(fileAccess_ & Fl_Preferences::SYSTEM_WRITE_OK) )
+ if ( ((root_type_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::SYSTEM) && !(fileAccess_ & Fl_Preferences::SYSTEM_WRITE_OK) )
return -1;
fl_make_path_for_file(filename_);
FILE *f = fl_fopen( filename_, "wb" );
@@ -1111,10 +1321,10 @@ char Fl_Preferences::RootNode::getPath( char *path, int pathlen ) {
}
// create a node that represents a group
-// - path must be a single word, prferable alnum(), dot and underscore only. Space is ok.
+// - path must be a single word, preferable alnum(), dot and underscore only. Space is ok.
Fl_Preferences::Node::Node( const char *path ) {
if ( path ) path_ = fl_strdup( path ); else path_ = 0;
- child_ = 0; next_ = 0; parent_ = 0;
+ first_child_ = 0; next_ = 0; parent_ = 0;
entry_ = 0;
nEntry_ = NEntry_ = 0;
dirty_ = 0;
@@ -1125,12 +1335,12 @@ Fl_Preferences::Node::Node( const char *path ) {
}
void Fl_Preferences::Node::deleteAllChildren() {
- Node *nx;
- for ( Node *nd = child_; nd; nd = nx ) {
- nx = nd->next_;
- delete nd;
+ Node *next_node = NULL;
+ for ( Node *current_node = first_child_; current_node; current_node = next_node ) {
+ next_node = current_node->next_;
+ delete current_node;
}
- child_ = 0L;
+ first_child_ = NULL;
dirty_ = 1;
updateIndex();
}
@@ -1139,16 +1349,16 @@ void Fl_Preferences::Node::deleteAllEntries() {
if ( entry_ ) {
for ( int i = 0; i < nEntry_; i++ ) {
if ( entry_[i].name ) {
- free( entry_[i].name );
- entry_[i].name = 0L;
+ ::free( entry_[i].name );
+ entry_[i].name = NULL;
}
if ( entry_[i].value ) {
- free( entry_[i].value );
- entry_[i].value = 0L;
+ ::free( entry_[i].value );
+ entry_[i].value = NULL;
}
}
free( entry_ );
- entry_ = 0L;
+ entry_ = NULL;
nEntry_ = 0;
NEntry_ = 0;
}
@@ -1157,22 +1367,22 @@ void Fl_Preferences::Node::deleteAllEntries() {
// delete this and all depending nodes
Fl_Preferences::Node::~Node() {
+ next_ = NULL;
+ parent_ = NULL;
deleteAllChildren();
deleteAllEntries();
deleteIndex();
if ( path_ ) {
- free( path_ );
- path_ = 0L;
+ ::free( path_ );
+ path_ = NULL;
}
- next_ = 0L;
- parent_ = 0L;
}
// recursively check if any entry is dirty (was changed after loading a fresh prefs file)
char Fl_Preferences::Node::dirty() {
if ( dirty_ ) return 1;
if ( next_ && next_->dirty() ) return 1;
- if ( child_ && child_->dirty() ) return 1;
+ if ( first_child_ && first_child_->dirty() ) return 1;
return 0;
}
@@ -1181,7 +1391,7 @@ void Fl_Preferences::Node::clearDirtyFlags() {
Fl_Preferences::Node *nd = this;
while (nd) {
nd->dirty_ = 0;
- if ( nd->child_ ) nd->child_->clearDirtyFlags();
+ if ( nd->first_child_ ) nd->first_child_->clearDirtyFlags();
nd = nd->next_;
}
}
@@ -1214,7 +1424,7 @@ int Fl_Preferences::Node::write( FILE *f ) {
else
fprintf( f, "%s\n", entry_[i].name );
}
- if ( child_ ) child_->write( f );
+ if ( first_child_ ) first_child_->write( f );
dirty_ = 0;
return 0;
}
@@ -1222,8 +1432,8 @@ int Fl_Preferences::Node::write( FILE *f ) {
// set the parent node and create the full path
void Fl_Preferences::Node::setParent( Node *pn ) {
parent_ = pn;
- next_ = pn->child_;
- pn->child_ = this;
+ next_ = pn->first_child_;
+ pn->first_child_ = this;
sprintf( nameBuffer, "%s/%s", pn->path_, path_ );
free( path_ );
path_ = fl_strdup( nameBuffer );
@@ -1234,7 +1444,7 @@ Fl_Preferences::RootNode *Fl_Preferences::Node::findRoot() {
Node *n = this;
do {
if (n->top_)
- return n->root_;
+ return n->root_node_;
n = n->parent();
} while (n);
return 0L;
@@ -1346,7 +1556,7 @@ Fl_Preferences::Node *Fl_Preferences::Node::find( const char *path ) {
return this;
if ( path[ len ] == '/' ) {
Node *nd;
- for ( nd = child_; nd; nd = nd->next_ ) {
+ for ( nd = first_child_; nd; nd = nd->next_ ) {
Node *nn = nd->find( path );
if ( nn ) return nn;
}
@@ -1392,7 +1602,7 @@ Fl_Preferences::Node *Fl_Preferences::Node::search( const char *path, int offset
if ( len > 0 && path[ len ] == 0 )
return this;
if ( len <= 0 || path[ len ] == '/' ) {
- for ( Node *nd = child_; nd; nd = nd->next_ ) {
+ for ( Node *nd = first_child_; nd; nd = nd->next_ ) {
Node *nn = nd->search( path, offset );
if ( nn ) return nn;
}
@@ -1408,7 +1618,7 @@ int Fl_Preferences::Node::nChildren() {
return nIndex_;
} else {
int cnt = 0;
- for ( Node *nd = child_; nd; nd = nd->next_ )
+ for ( Node *nd = first_child_; nd; nd = nd->next_ )
cnt++;
return cnt;
}
@@ -1444,7 +1654,7 @@ Fl_Preferences::Node *Fl_Preferences::Node::childNode( int ix ) {
int n = nChildren();
ix = n - ix -1;
Node *nd;
- for ( nd = child_; nd; nd = nd->next_ ) {
+ for ( nd = first_child_; nd; nd = nd->next_ ) {
if ( !ix-- ) break;
if ( !nd ) break;
}
@@ -1454,23 +1664,25 @@ Fl_Preferences::Node *Fl_Preferences::Node::childNode( int ix ) {
// remove myself from the list and delete me (and all children)
char Fl_Preferences::Node::remove() {
- Node *nd = 0, *np;
- if ( parent() ) {
- nd = parent()->child_; np = 0L;
+ Node *nd = NULL, *np = NULL;
+ Node *parent_node = parent();
+ if ( parent_node ) {
+ nd = parent_node->first_child_; np = NULL;
for ( ; nd; np = nd, nd = nd->next_ ) {
if ( nd == this ) {
if ( np )
- np->next_ = nd->next_;
+ np->next_ = next_;
else
- parent()->child_ = nd->next_;
+ parent_node->first_child_ = next_;
+ next_ = NULL;
break;
}
}
- parent()->dirty_ = 1;
- parent()->updateIndex();
+ parent_node->dirty_ = 1;
+ parent_node->updateIndex();
}
delete this;
- return ( nd != 0 );
+ return ( nd != NULL );
}
void Fl_Preferences::Node::createIndex() {
@@ -1482,7 +1694,7 @@ void Fl_Preferences::Node::createIndex() {
}
Node *nd;
int i = 0;
- for (nd = child_; nd; nd = nd->next_, i++) {
+ for (nd = first_child_; nd; nd = nd->next_, i++) {
index_[n-i-1] = nd;
}
nIndex_ = n;
@@ -1494,9 +1706,10 @@ void Fl_Preferences::Node::updateIndex() {
}
void Fl_Preferences::Node::deleteIndex() {
- if (index_) free(index_);
+ if (index_)
+ ::free(index_);
+ index_ = NULL;
NIndex_ = nIndex_ = 0;
- index_ = 0;
indexed_ = 0;
}