Where does Fl_Preferences file actually get stored?

105 views
Skip to first unread message

Rob McDonald

unread,
Apr 23, 2015, 7:45:04 PM4/23/15
to fltkg...@googlegroups.com
I'm trying to understand the apparently mystical behavior of Fl_Preferences.  The docs say it is a plain text file, but I can't figure out where that file is -- or where its name is specified in the code that uses it.  I'm currently running on MacOS.

Thanks for any pointers.

Rob

Greg Ercolano

unread,
Apr 23, 2015, 8:29:59 PM4/23/15
to fltkg...@googlegroups.com
On 04/23/15 16:45, Rob McDonald wrote:
> I'm trying to understand the apparently mystical behavior of Fl_Preferences. The docs say it is a plain text file, but I can't figure out where that file is -- or where its name is specified in the code that uses it. I'm currently running on MacOS.
>
> Thanks for any pointers.

Had to look at the code, I've never used it myself.

Not sure why the docs don't cover this; could be because the platform
specific logic varies so much.

I did a 'quick and dirty' reading of the code:


System:
Mac: /Library/Preferences/<vendor>/<app>.prefs
Unix: /etc/fltk/<vendor>/<appname>.prefs
Windows: Uses the registry somehow to determine the path, don't ask me

User:
Mac: $HOME/Library/Preferences/<vendor>/<appname>.prefs
Unix: $HOME/.fltk/<vendor>/<app>.prefs
Windows: Uses the registry somehow to determine the path, don't ask me


Not sure why the User/Windows technique doesn't just use the HOMEPATH,
but maybe its poking around in the registry ends up resolving to that,
I'm not sure. I'll bet there's good reasons for what it does.. perhaps
Microsoft's own documentation covers this.

MacArthur, Ian (Selex ES, UK)

unread,
Apr 24, 2015, 4:57:44 AM4/24/15
to fltkg...@googlegroups.com

> User:
> Mac: $HOME/Library/Preferences/<vendor>/<appname>.prefs
> Unix: $HOME/.fltk/<vendor>/<app>.prefs
> Windows: Uses the registry somehow to determine the path,
> don't ask me
>
>
> Not sure why the User/Windows technique doesn't just use the
> HOMEPATH,
> but maybe its poking around in the registry ends up resolving to
> that,
> I'm not sure. I'll bet there's good reasons for what it does..
> perhaps
> Microsoft's own documentation covers this.

In practice, it typically resolves to something like:

C:\Users\<user_name>\AppData\Local\<vendor>\<appname> etc...

Though depending on how your machine is set up, the "Local" part might be mapped into the "Roaming" profile. It might be this that makes it easier to check via the registry, since the registry will presumably know whether it is meant to map the local or roaming profile for any given login account...


Selex ES Ltd
Registered Office: Sigma House, Christopher Martin Road, Basildon, Essex SS14 3EL
A company registered in England & Wales. Company no. 02426132
********************************************************************
This email and any attachments are confidential to the intended
recipient and may also be privileged. If you are not the intended
recipient please delete it from your system and notify the sender.
You should not copy it or use it for any purpose nor disclose or
distribute its contents to any other person.
********************************************************************

Greg Ercolano

unread,
Apr 24, 2015, 10:03:38 AM4/24/15
to fltkg...@googlegroups.com
On 04/24/15 01:57, MacArthur, Ian (Selex ES, UK) wrote:

>> Not sure why the User/Windows technique doesn't just use the HOMEPATH,
>> but maybe its poking around in the registry ends up resolving to that,
>> I'm not sure. I'll bet there's good reasons for what it does.. perhaps
>> Microsoft's own documentation covers this.
>
> In practice, it typically resolves to something like:
>
> C:\Users\<user_name>\AppData\Local\<vendor>\<appname> etc...
>
> Though depending on how your machine is set up, the "Local" part might be
> mapped into the "Roaming" profile. It might be this that makes it easier
> to check via the registry, since the registry will presumably know whether
> it is meant to map the local or roaming profile for any given login account...

Hmm, I thought the roaming profile stuff affects the contents
of the HOMEPATH variable?

https://technet.microsoft.com/en-us/library/cc766489%28v=ws.10%29.aspx

"""
Redirect to the following location:
This option redirects the named folder to the exact path listed in the Root Path.
This has the capacity to redirect multiple users using the same share path for
the redirected folder. You could use this option so multiple users have the
same Desktop or Start Menu.

Note
Folder redirection only supports %USERNAME%, %USERPROFILE%, %HOMESHARE%,
*and %HOMEPATH% environment variables.*
"""

I believe I use that for preferences in my fltk apps, and fall
back to the windows temp directory (with the user's name in the
filename) if that doesn't work.

I try to avoid the registry, so that when folks ask where the
preferences are, I just say "look in your %HOMEPATH%", as opposed
to having to go into regedit and walk through its hopelessly
byzantine maze of wacky key names.

Richard Sanders

unread,
Apr 24, 2015, 4:19:49 PM4/24/15
to fltkg...@googlegroups.com



I'm trying to understand the apparently mystical behavior of Fl_Preferences.  The docs say it is a plain text file, but I can't figure out where that file is -- or where its name is specified in the code that uses it.  I'm currently running on MacOS.



If you use
Fl_Preferences::Fl_Preferences ( const char *  path,


const char *  vendor,


const char *  application 

)
then you can determine where the file is stored. 

Greg Ercolano

unread,
Apr 24, 2015, 5:22:13 PM4/24/15
to fltkg...@googlegroups.com
    Hmm, that's a constructor that lets you set the path
    for Fl_Preferences to use, but I don't think it lets you
    get what it uses by default if you don't specify a path..
    such as our sudoku demo program that uses:

        Fl_Preferences  Sudoku::prefs_(Fl_Preferences::USER, "fltk.org", "sudoku");

    ..to initialize its preferences, without a path, just the vendor and app names.

    I think the OP is looking for a way to find out the location
    it uses in such a case where no path is specified.
   
    But you're right, Fl_Preferences probably does have a method
    to get at the location info it uses internally.. I think maybe
    the getUserdataPath()
method might give you that info..? The docs:



char Fl_Preferences::getUserdataPath(char *path,
                                     int pathlen)

Creates a path that is related to the preferences file and that is usable
for additional application data.

This function creates a directory that is named after the preferences
database without the .prefs extension and located in the same directory.
It then fills the given buffer with the complete path name.

Example:
    Fl_Preferences prefs( USER, "matthiasm.com", "test" );
    char path[FL_PATH_MAX];
    prefs.getUserdataPath( path );

..creates the preferences database in (MS Windows):

    c:/Documents and Settings/matt/Application Data/matthiasm.com/test.prefs

..and returns the userdata path:

    c:/Documents and Settings/matt/Application Data/matthiasm.com/test/

Parameters
    [out] path     buffer for user data path
    [in]  pathlen  size of path buffer (should be at least FL_PATH_MAX)



Haven't tried it, but that sounds like it might do the trick.

Note: Kinda surprised that a 'get' method also 'creates a directory',
e.g. with mkdir(). Looking at the code, I think it actually does change
the file system; it makes calls to fl_make_path() and fl_chmod() in there..
so be somewhat aware of that.

Matthias Melcher

unread,
Apr 25, 2015, 3:16:47 AM4/25/15
to fltkg...@googlegroups.com

OK, this is really old code. I'll try to answer all this.

The Preferences were programmed before XML became mainstream. The text format is similar (but not the same) to the Microsoft registry format. It is the same format on all platforms though, so you can migrate your settings.

The location of the file was chosen to comply with the "usual" location of preferences as defined in the various style guides of the lat 90ies. The directory that can be retrieved is also based on those guidelines, but doesn't necessarily return the same location as the preferences file.

The MSWindows location relies on registry entries as defined by Microsoft. Where this location will be, only Microsoft knows.

The OS X system uses the Preferences folder on the system or user level.

The Unix solution was already described.

Why does reading a value create a file? Well, I saw the preferences as a database, and tried to provide database access, not file access (this is why I never published the format of the file or the location. It simply should not matter). Reading an entry creates the entire database structure and file. You can mix reading and writing calls at any time. It's always random access, so it always requires the infrastructure.

There are of course flaws. There is no versioning or conflict detection. If multiple instances of an app are openeing, flushing or closing the same database, data may (or likely will) be lost.

Hope that helps,

Matthias

Greg Ercolano

unread,
Apr 25, 2015, 10:48:56 AM4/25/15
to fltkg...@googlegroups.com
On 04/25/15 00:16, Matthias Melcher wrote:
OK, this is really old code. I'll try to answer all this.

The Preferences were programmed before XML became mainstream. 
The text format is similar (but not the same) to the Microsoft
registry format. It is the same format on all platforms though,
so you can migrate your settings.

    Thanks for the extra info, Matt!

    BTW, the non-XML bit sounds fine to me.

    I was always "meh" about XML because it's so hard to human-read without a tool.
    I also don't like how saving in XML almost doubles in size compared to key/value..
    XML is more overhead than data.

    I'd much rather see:

        "employee": "Fred Flintstone"
        {
            "id": 12,
            "department": "quarry",
            "contractor": false
        }

    ..instead of

              <key>employee</key>
              <string>Fred Flintstone</string>
              <dict>
                <key>id</key>
                <integer>12</integer>
                <key>department</key>
                <string>quarry</string>
                <key>contractor</key>
                <true/>
              </dict>    

    ..that's just so much noise.

    I find myself using JSON more and more for moving data around,
    such as reports generated by command line tools to be ingested
    by python + perl scripts. This is by overwhelming requests from customers.

    JSON is more like the key: value pair stuff; human readable if indented it
    properly, and very low overhead, deals with quoting, dicts and arrays reasonably.

    Also, it's trivial to write parsers/generators for JSON; the format is simple.
    And modules exist for perl/python already.



Rob McDonald

unread,
Apr 25, 2015, 12:08:02 PM4/25/15
to fltkg...@googlegroups.com, erco_...@seriss.com
Thanks everyone for the interest, replies, and discussion.  As the OP, I figured I should pop back in.

Greg's first reply pretty much satisfied my needs -- everything else has been extra informative.

My confusion stemmed from my not understanding the database-like mode of operation for Preferences.  From the documentation, I came at this expecting something much more file oriented.  The program I encountered Fl_Preferences in had three separate lightweight users.

I was expecting file behavior yet I couldn't figure out where the file was designated, opened, passed around, or closed.  This was rather confusing.  Poking around on my file system, I couldn't figure out where this data was going, all seemed quite mysterious.

Now that all is revealed, I'd say the system is pretty slick.  It provides a simple to use preferences system that works across platforms.  Since prefs are kept outside the normal distribution files, they'll persist across version updates, etc.

Thanks,

Rob

anmol....@gmail.com

unread,
Apr 20, 2021, 12:52:09 PM4/20/21
to fltk.general

I had to access the filename myself. I used this as a method.
// private
char m_prefsPath[FL_PATH_MAX];

// public
char* getPrefsFile() {
char path[FL_PATH_MAX];
     getUserdataPath(path, sizeof(m_prefsPath));
      m_prefsPath[strlen(path)-1] = '\0';
      std::ostringstream prefsFile;
      prefsFile << path<< ".prefs";
      strcpy(m_prefsPath, prefsFile.str().c_str());
      return m_prefsPath;

anmol....@gmail.com

unread,
Apr 30, 2021, 7:16:49 AM4/30/21
to fltk.general
I am copying a default version of the prefs file into a string during compilation. When the constructor is called (i.e. runtime), I detect the absence of a file and copy the default file.
Can I confirm that the prefs file is created *ONLY* after the first read (i.e. get()) call ?

So
        prefs = Fl_Preferences(Fl_Preferences::USER, vendor, product);
will not create a prefs file until the first
prefs.get() or prefs.set()


On Saturday, April 25, 2015 at 12:46:47 PM UTC+5:30 Matthias Melcher wrote:

Why does reading a value create a file? Well, I saw the preferences as a database, and tried to provide database access, not file access (this is why I never published the format of the file or the location. It simply should not matter). Reading an entry creates the entire database structure and file. You can mix reading and writing calls at any time. It's always random access, so it always requires the infrastructure.

Matthias
Reply all
Reply to author
Forward
0 new messages