$HOME/data dirs for *nix/OSX/Windows
------------------------------------

This is from a Lyx discussion, but it's the same problem I have for ipython.  Use this info when rewriting:

##########################################################################
My Documents et al --- success
Von: Angus Leeming <leeming-0hXrFu2P2+c@public.gmane.org>
Datum: Dienstag 21 Dezember 2004 03:21:50 vormittags
Gruppen: gmane.editors.lyx.devel
Keine Referenzen

It turns out that Jürgen's suggested way to ascertain the different 
Windows folders is straightforward to implement. No need to use the .net 
framework; it all exists in the standard WinAPI.

Question. What should we do in the unlikely event that these calls fail? 
   Post a warning or terminate?

Angus

$g++ -o trial trial.C

$ ./trial
APPDATA is C:\Documents and Settings\Angus\Application Data
COMMON_APPDATA is C:\Documents and Settings\All Users\Application Data
PERSONAL is C:\Documents and Settings\Angus\My Documents


$ cat trial.C
#include <shlobj.h>
#include <iostream>
#include <string>

// Needed for MinGW:
#ifndef SHGFP_TYPE_CURRENT
# define SHGFP_TYPE_CURRENT 0
#endif

std::string const folder_path(int folder_id)
{
         char folder_path[MAX_PATH + 1];
         if (SUCCEEDED(SHGetFolderPath(0, folder_id, 0,
                                      SHGFP_TYPE_CURRENT, folder_path)))
                 return folder_path;
         return std::string();
}


std::string const id_as_string(int folder_id)
{
         if (folder_id == CSIDL_APPDATA)
                 return "APPDATA";
         if (folder_id == CSIDL_COMMON_APPDATA)
                 return "COMMON_APPDATA";
         if (folder_id == CSIDL_PERSONAL)
                 return "PERSONAL";
         return std::string();
}

void print_success(int folder_id)
{
         std::string const folder_name = folder_path(folder_id);
         std::string const id_str = id_as_string(folder_id);

         if (folder_name.empty())
                 std::cout << "Unable to ascertain " << id_str
                          << " folder\n";
         else
                 std::cout << id_str << " is " << folder_name << '\n';
}


int main()
{
         print_success(CSIDL_APPDATA);
         print_success(CSIDL_COMMON_APPDATA);
         print_success(CSIDL_PERSONAL);

         return 0;
}

##########################################################################
Ok, then here's the proposal. Add to class (13x)/namespace(14x) os the 
following functions that are set in os::init(int argc, char argv[]):

// The OS-dependent directory to which an application's
// system-wide data directory should generally be added.
string const & os::system_appdir() {
        // returns COMMON_APPDATA folder on Windows
        // returns ??? on MacOS
        // returns an empty string on Unix
}

// The OS-dependent directory to which an application's
// user-specific data directory should generally be added.
string const & os::user_appdir() {
        // returns APPDATA folder on Windows
        // returns ??? on MacOS
        // returns $HOME on Unix
}

// The OS-dependent directory to which a user's
// documents should generally be added.
string const & os::document_dir() {
        // returns PERSONAL folder on Windows
        // returns ??? on MacOS
        // returns $HOME on Unix
}

Then use these in lyx_main.C's LyX::init() (13x) or in path_defines.C's 
setLyxPaths() (14x) to help set system_lyxdir, user_lyxdir and in 
lyxrc.C's constructor to set the default lyxrc::document_path.

##########################################################################

Angus> // The OS-dependent directory to which an application's 
Angus> // system-wide data directory should generally be added. 
Angus> string const & os::system_appdir() { 
Angus> // returns COMMON_APPDATA folder on Windows 

On windows, I believe the right place to have the data directory is
the directory where the binary lives. There may even be an API
function to get this value directly.

Angus> // returns ??? on MacOS 

There is also an API for that. See:
http://doc.trolltech.com/3.3/mac-differences.html#7-1

Angus> // returns an empty string on Unix

I think this one should contain the code that lives in path_defines
for now (with the stuff that follows symlinks)

Angus> }

Angus> // The OS-dependent directory to which an application's 
Angus> // user-specific data directory should generally be added.
Angus> string const & os::user_appdir() { 
Angus> // returns APPDATA folder on Windows 

Or should it be APPDATA/LyX/ ?

Angus> // returns ??? on MacOS 

Currently this is ${HOME}/Library/Preferences/LyX

Angus> // returns $HOME on Unix

Or return ${HOME}/.PACKAGE

Angus> }

Angus> // The OS-dependent directory to which a user's 
Angus> // documents should generally be added. 
Angus> string const & os::document_dir() { 
Angus> // returns PERSONAL folder on Windows 

Yes.

Angus> // returns ??? on MacOS 

I think it's HOME

Angus> // returns $HOME on Unix

Angus> }

You forgot the locale directory.

Angus> Then use these in lyx_main.C's LyX::init() (13x) or in
Angus> path_defines.C's setLyxPaths() (14x) to help set system_lyxdir,
Angus> user_lyxdir and in lyxrc.C's constructor to set the default
Angus> lyxrc::document_path.

I think we should reimplement setLyXPaths for each of these cases. It
will be much simpler.

Then there will be the special case of build directory to enable
running in place. This one may be trickier.

##########################################################################