From 6c28edea55d13be0fac5cf4607043c7d96c6defc Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Mon, 10 Jun 2013 21:37:00 +0200 Subject: [PATCH] SGPath: new helpers and static members for home and desktop path --- simgear/misc/sg_path.cxx | 99 ++++++++++++++++++++++++++++++++++++++++ simgear/misc/sg_path.hxx | 27 +++++++++++ 2 files changed, 126 insertions(+) diff --git a/simgear/misc/sg_path.cxx b/simgear/misc/sg_path.cxx index 7db261da..9267cedf 100644 --- a/simgear/misc/sg_path.cxx +++ b/simgear/misc/sg_path.cxx @@ -26,9 +26,11 @@ #include #include +#include #include #include #include +#include #ifdef _WIN32 # include @@ -38,6 +40,7 @@ #include using std::string; +using simgear::strutils::starts_with; /** * define directory path separators @@ -153,6 +156,14 @@ void SGPath::append( const string& p ) { _cached = false; } +//------------------------------------------------------------------------------ +SGPath SGPath::operator/( const std::string& p ) const +{ + SGPath ret = *this; + ret.append(p); + return ret; +} + //add a new path component to the existing path string void SGPath::add( const string& p ) { append( sgSearchPathSep+p ); @@ -483,6 +494,94 @@ bool SGPath::rename(const SGPath& newName) return true; } +//------------------------------------------------------------------------------ +SGPath SGPath::fromEnv(const char* name, const SGPath& def) +{ + const char* val = getenv(name); + if( val && val[0] ) + return SGPath(val); + return def; +} + +#ifdef _WIN32 +//------------------------------------------------------------------------------ +SGPath SGPath::home() +{ + // TODO + return SGPath(); +} +#else +//------------------------------------------------------------------------------ +SGPath SGPath::home() +{ + return fromEnv("HOME"); +} +#endif + +#ifdef _WIN32 +//------------------------------------------------------------------------------ +SGPath SGPath::desktop() +{ + // TODO + return SGPath(); +} +#elif __APPLE__ +#include + +//------------------------------------------------------------------------------ +SGPath SGPath::desktop() +{ + FSRef ref; + OSErr err = FSFindFolder(kUserDomain, kDesktopFolderType, false, &ref); + if (err) { + return SGPath(); + } + + unsigned char path[1024]; + if (FSRefMakePath(&ref, path, 1024) != noErr) { + return SGPath(); + } + + return SGPath((const char*) path); +} +#else +//------------------------------------------------------------------------------ +SGPath SGPath::desktop() +{ + // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html + + // $XDG_CONFIG_HOME defines the base directory relative to which user specific + // configuration files should be stored. If $XDG_CONFIG_HOME is either not set + // or empty, a default equal to $HOME/.config should be used. + const SGPath user_dirs = fromEnv("XDG_CONFIG_HOME", home() / ".config") + / "user-dirs.dirs"; + + // Format is XDG_xxx_DIR="$HOME/yyy", where yyy is a shell-escaped + // homedir-relative path, or XDG_xxx_DIR="/yyy", where /yyy is an absolute + // path. No other format is supported. + const std::string DESKTOP = "XDG_DESKTOP_DIR=\""; + + std::ifstream user_dirs_file( user_dirs.c_str() ); + std::string line; + while( std::getline(user_dirs_file, line).good() ) + { + if( !starts_with(line, DESKTOP) || *line.rbegin() != '"' ) + continue; + + // Extract dir from XDG_DESKTOP_DIR="" + line = line.substr(DESKTOP.length(), line.length() - DESKTOP.length() - 1 ); + + const std::string HOME = "$HOME"; + if( starts_with(line, HOME) ) + return home() / simgear::strutils::unescape(line.substr(HOME.length())); + + return SGPath(line); + } + + return home() / "Desktop"; +} +#endif + std::string SGPath::realpath() const { #if (defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED <= 1050) diff --git a/simgear/misc/sg_path.hxx b/simgear/misc/sg_path.hxx index 1f9dfbe7..bd27694f 100644 --- a/simgear/misc/sg_path.hxx +++ b/simgear/misc/sg_path.hxx @@ -98,6 +98,13 @@ public: * @param p additional path component */ void append( const std::string& p ); + /** + * Get a copy of this path with another piece appended. + * + * @param p additional path component + */ + SGPath operator/( const std::string& p ) const; + /** * Append a new piece to the existing path. Inserts a search path * separator to the existing path and the new patch component. @@ -226,6 +233,26 @@ public: * or if the destination already exists, or is not writeable */ bool rename(const SGPath& newName); + + /** + * Get a path stored in the environment variable with the given \a name. + * + * @param name Name of the environment variable + * @param def Default path to return if the environment variable does not + * exist or is empty. + */ + static SGPath fromEnv(const char* name, const SGPath& def = SGPath()); + + /** + * Get path to user's home directory + */ + static SGPath home(); + + /** + * Get path to the user's desktop directory + */ + static SGPath desktop(); + private: void fix(); -- 2.39.5