diff options
| author | Matthias Melcher <github@matthiasm.com> | 2022-01-23 22:35:21 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-01-23 22:35:21 +0100 |
| commit | 7308bcdb74e34626c6459699cb57371afd7b343b (patch) | |
| tree | a20d8561303af12d70ebab7f23254e2eb2108ed5 /src | |
| parent | 04ccc8cc46c45b81e6138bec0b48a188c4ffe406 (diff) | |
Preferences XDG path (#377)
* Preferences: remove CamelCase from public interface.
* Prefs: documentation.
* Prefs: updating Doxygen comments
* XDG conforming preferences path
Diffstat (limited to 'src')
| -rw-r--r-- | src/Fl_Preferences.cxx | 58 | ||||
| -rw-r--r-- | src/drivers/X11/Fl_X11_System_Driver.cxx | 55 |
2 files changed, 83 insertions, 30 deletions
diff --git a/src/Fl_Preferences.cxx b/src/Fl_Preferences.cxx index 83fa3da99..b3c3c9c9f 100644 --- a/src/Fl_Preferences.cxx +++ b/src/Fl_Preferences.cxx @@ -63,7 +63,7 @@ static int clocale_sscanf(const char *input, const char *format, ...) \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() { +const char *Fl_Preferences::new_UUID() { Fl::system_driver()->newUUID(uuidBuffer); return uuidBuffer; } @@ -126,7 +126,7 @@ unsigned int Fl_Preferences::file_access() 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[out] buffer write the resulting 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 @@ -157,10 +157,16 @@ Fl_Preferences::Root Fl_Preferences::filename( char *buffer, size_t buffer_size, /** - 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_L` - or `Fl_Preferences::SYSTEM_L`. + The constructor creates a group that manages key/value pairs and + child groups. + + Preferences can be stored per user using the root type + `Fl_Preferences::USER_L`, or stored system-wide using + `Fl_Preferences::SYSTEM_L`. + + Groups and key/value pairs can be read and written randomly. Reading undefined + values will return the default value. Writing undefined values will create + all required groups and key/vlaue pairs. This constructor creates the <i>base</i> instance for all following entries and reads the database from disk into memory if it exists. @@ -192,12 +198,22 @@ Fl_Preferences::Root Fl_Preferences::filename( char *buffer, size_t buffer_size, 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 + + The \c SYSTEM preferences filename 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 + For backward compatibility, the old \c USER `.prefs` file naming scheme + <tt>\$(directory)/.fltk/\$(vendor)/\$(application).prefs</tt> is checked first. + If that file does not exist, the environment variable `$XDG_CONFIG_HOME` is + read as a base directory. If `$XDG_CONFIG_HOME` not set, the base directory + defaults to `$HOME/.config/`. + + The user preferences will be stored in + <tt>\$(directory)/\$(vendor)/\$(application).prefs</tt>, The user data path + will be + <tt>\$(directory)/\$(vendor)/\$(application)/</tt> + + 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. @@ -270,11 +286,11 @@ Fl_Preferences::Fl_Preferences( Fl_Preferences &parent, const char *group ) { 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 + - 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); @@ -457,7 +473,7 @@ const char *Fl_Preferences::group( int num_group ) { \param[in] key name of group that is searched for \return 0 if no group by that name was found */ -char Fl_Preferences::groupExists( const char *key ) { +char Fl_Preferences::group_exists( const char *key ) { return node->search( key ) ? 1 : 0 ; } @@ -470,7 +486,7 @@ char Fl_Preferences::groupExists( const char *key ) { \param[in] group name of the group to delete \return 0 if call failed */ -char Fl_Preferences::deleteGroup( const char *group ) { +char Fl_Preferences::delete_group( const char *group ) { Node *nd = node->search( group ); if ( nd ) return nd->remove(); return 0; @@ -479,7 +495,7 @@ char Fl_Preferences::deleteGroup( const char *group ) { /** Delete all groups. */ -char Fl_Preferences::deleteAllGroups() { +char Fl_Preferences::delete_all_groups() { node->deleteAllChildren(); return 1; } @@ -511,7 +527,7 @@ const char *Fl_Preferences::entry( int index ) { \param[in] key name of entry that is searched for \return 0 if entry was not found */ -char Fl_Preferences::entryExists( const char *key ) { +char Fl_Preferences::entry_exists( const char *key ) { return node->getEntry( key )>=0 ? 1 : 0 ; } @@ -523,14 +539,14 @@ char Fl_Preferences::entryExists( const char *key ) { \param[in] key name of entry to delete \return 0 if deleting the entry failed */ -char Fl_Preferences::deleteEntry( const char *key ) { +char Fl_Preferences::delete_entry( const char *key ) { return node->deleteEntry( key ); } /** Delete all entries. */ -char Fl_Preferences::deleteAllEntries() { +char Fl_Preferences::delete_all_entries() { node->deleteAllEntries(); return 1; } @@ -1012,7 +1028,7 @@ int Fl_Preferences::size( const char *key ) { \see Fl_Preferences::Fl_Preferences(Root, const char*, const char*) */ -char Fl_Preferences::getUserdataPath( char *path, int pathlen ) { +char Fl_Preferences::get_userdata_path( char *path, int pathlen ) { if ( rootNode ) return rootNode->getPath( path, pathlen ); return 0; diff --git a/src/drivers/X11/Fl_X11_System_Driver.cxx b/src/drivers/X11/Fl_X11_System_Driver.cxx index 9ffae3d45..71becad49 100644 --- a/src/drivers/X11/Fl_X11_System_Driver.cxx +++ b/src/drivers/X11/Fl_X11_System_Driver.cxx @@ -459,19 +459,19 @@ char *Fl_X11_System_Driver::preference_rootnode(Fl_Preferences * /*prefs*/, Fl_P { static char *filename = 0L; if (!filename) filename = (char*)::calloc(1, FL_PATH_MAX); - const char *e; + const char *home; switch (root&Fl_Preferences::ROOT_MASK) { case Fl_Preferences::USER: - e = getenv("HOME"); + home = getenv("HOME"); // make sure that $HOME is set to an existing directory - if ( (e==0L) || (e[0]==0) || (::access(e, F_OK)==-1) ) { + if ( (home==NULL) || (home[0]==0) || (::access(home, F_OK)==-1) ) { struct passwd *pw = getpwuid(getuid()); - e = pw->pw_dir; + home = pw->pw_dir; } - if ( (e==0L) || (e[0]==0) || (::access(e, F_OK)==-1) ) { - return 0L; + if ( (home==0L) || (home[0]==0) || (::access(home, F_OK)==-1) ) { + return NULL; } else { - strlcpy(filename, e, FL_PATH_MAX); + strlcpy(filename, home, FL_PATH_MAX); if (filename[strlen(filename)-1] != '/') strlcat(filename, "/", FL_PATH_MAX); strlcat(filename, ".fltk/", FL_PATH_MAX); @@ -483,13 +483,50 @@ char *Fl_X11_System_Driver::preference_rootnode(Fl_Preferences * /*prefs*/, Fl_P } // Make sure that the parameters are not NULL - if ( (vendor==0L) || (vendor[0]==0) ) + if ( (vendor==NULL) || (vendor[0]==0) ) vendor = "unknown"; - if ( (application==0L) || (application[0]==0) ) + if ( (application==NULL) || (application[0]==0) ) application = "unknown"; snprintf(filename + strlen(filename), FL_PATH_MAX - strlen(filename), "%s/%s.prefs", vendor, application); + + // If this is the SYSTEM path, we are done + if ((root&Fl_Preferences::ROOT_MASK)!=Fl_Preferences::USER) + return filename; + + // If the legacy file exists, we are also done + if (::access(filename, F_OK)==0) + return filename; + + // This is USER mode, and there is no legacy file. Create an XDG conforming path. + // Check $XDG_CONFIG_HOME, and if it isn't set, default to $HOME/.config + const char *xdg = getenv("XDG_CONFIG_HOME"); + if (xdg==NULL) { + xdg = "~/.config"; + } + filename[0] = 0; + if (strncmp(xdg, "~/", 2)==0) { + strlcpy(filename, home, FL_PATH_MAX); + strlcat(filename, "/", FL_PATH_MAX); + strlcat(filename, xdg+2, FL_PATH_MAX); + } else if (strncmp(xdg, "$HOME/", 6)==0) { + strlcpy(filename, home, FL_PATH_MAX); + strlcat(filename, "/", FL_PATH_MAX); + strlcat(filename, xdg+6, FL_PATH_MAX); + } else if (strncmp(xdg, "${HOME}/", 8)==0) { + strlcpy(filename, home, FL_PATH_MAX); + strlcat(filename, "/", FL_PATH_MAX); + strlcat(filename, xdg+8, FL_PATH_MAX); + } else { + strlcpy(filename, xdg, FL_PATH_MAX); + } + strlcat(filename, "/", FL_PATH_MAX); + strlcat(filename, vendor, FL_PATH_MAX); + strlcat(filename, "/", FL_PATH_MAX); + strlcat(filename, application, FL_PATH_MAX); + strlcat(filename, ".prefs", FL_PATH_MAX); + return filename; } |
