diff --git a/dtool/src/dtoolutil/Sources.pp b/dtool/src/dtoolutil/Sources.pp index 928befea15..a7d5afaff8 100644 --- a/dtool/src/dtoolutil/Sources.pp +++ b/dtool/src/dtoolutil/Sources.pp @@ -4,6 +4,7 @@ #if $[ne $[PLATFORM], FreeBSD] #define UNIX_SYS_LIBS dl #endif + #define WIN_SYS_LIBS shell32.lib #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx diff --git a/dtool/src/dtoolutil/executionEnvironment.cxx b/dtool/src/dtoolutil/executionEnvironment.cxx index 0535258b74..02e64e7c5c 100644 --- a/dtool/src/dtoolutil/executionEnvironment.cxx +++ b/dtool/src/dtoolutil/executionEnvironment.cxx @@ -186,6 +186,18 @@ ns_get_environment_variable(const string &var) const { if (evi != _variables.end()) { return (*evi).second; } + + // Some special case variables. We virtually stuff these values + // into the Panda environment, shadowing whatever values they have + // the true environment, so they can be used in config files. + if (var == "TEMP") { + return Filename::get_temp_directory().to_os_specific(); + } else if (var == "USER_APPDATA") { + return Filename::get_user_appdata_directory().to_os_specific(); + } else if (var == "COMMON_APPDATA") { + return Filename::get_common_appdata_directory().to_os_specific(); + } + #ifdef PREREAD_ENVIRONMENT return string(); #else diff --git a/dtool/src/dtoolutil/filename.cxx b/dtool/src/dtoolutil/filename.cxx index c2464d7d5a..d4fe101ae5 100644 --- a/dtool/src/dtoolutil/filename.cxx +++ b/dtool/src/dtoolutil/filename.cxx @@ -53,6 +53,10 @@ bool Filename::_got_temp_directory; Filename Filename::_temp_directory; +bool Filename::_got_user_appdata_directory; +Filename Filename::_user_appdata_directory; +bool Filename::_got_common_appdata_directory; +Filename Filename::_common_appdata_directory; TypeHandle Filename::_type_handle; #ifdef WIN32 @@ -459,23 +463,106 @@ get_temp_directory() { } } - if (!_got_temp_directory) { - // if $TMP or $TEMP contain bogus strings, GetTempPath() may - // return a bogus string. - _temp_directory = ExecutionEnvironment::get_cwd(); - _got_temp_directory = true; - } - #else // Posix case. _temp_directory = "/tmp"; _got_temp_directory = true; #endif // WIN32 + + if (!_got_temp_directory) { + // Fallback case. + _temp_directory = ExecutionEnvironment::get_cwd(); + _got_temp_directory = true; + } } return _temp_directory; } +//////////////////////////////////////////////////////////////////// +// Function: Filename::get_user_appdata_directory +// Access: Published +// Description: Returns a path to a system-defined directory +// appropriate for creating a subdirectory for storing +// application-specific data, specific to the current +// user. +//////////////////////////////////////////////////////////////////// +const Filename &Filename:: +get_user_appdata_directory() { + if (!_got_user_appdata_directory) { +#ifdef WIN32 + char buffer[MAX_PATH]; + + if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_APPDATA, true)) { + _user_appdata_directory = from_os_specific(buffer); + if (_user_appdata_directory.is_directory()) { + if (_user_appdata_directory.make_canonical()) { + _got_user_appdata_directory = true; + } + } + } + +#else + // Posix case. + char *home = getenv("HOME"); + if (home != (char *)NULL) { + _user_appdata_directory = from_os_specific(home); + if (_user_appdata_directory.is_directory()) { + if (_user_appdata_directory.make_canonical()) { + _got_user_appdata_directory = true; + } + } + } +#endif // WIN32 + + if (!_got_user_appdata_directory) { + // Fallback case. + _user_appdata_directory = ExecutionEnvironment::get_cwd(); + _got_user_appdata_directory = true; + } + } + + return _user_appdata_directory; +} + +//////////////////////////////////////////////////////////////////// +// Function: Filename::get_common_appdata_directory +// Access: Published +// Description: Returns a path to a system-defined directory +// appropriate for creating a subdirectory for storing +// application-specific data, common to all users. +//////////////////////////////////////////////////////////////////// +const Filename &Filename:: +get_common_appdata_directory() { + if (!_got_common_appdata_directory) { +#ifdef WIN32 + char buffer[MAX_PATH]; + + if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_COMMON_APPDATA, true)) { + _common_appdata_directory = from_os_specific(buffer); + if (_common_appdata_directory.is_directory()) { + if (_common_appdata_directory.make_canonical()) { + _got_common_appdata_directory = true; + } + } + } + +#else + // Posix case. + _common_appdata_directory = "/var"; + _got_common_appdata_directory = true; +#endif // WIN32 + + if (!_got_common_appdata_directory) { + // Fallback case. + _common_appdata_directory = ExecutionEnvironment::get_cwd(); + _got_common_appdata_directory = true; + } + } + + return _common_appdata_directory; +} + //////////////////////////////////////////////////////////////////// // Function: Filename::set_fullpath // Access: Published diff --git a/dtool/src/dtoolutil/filename.h b/dtool/src/dtoolutil/filename.h index fb5177a382..3c5f5a1300 100644 --- a/dtool/src/dtoolutil/filename.h +++ b/dtool/src/dtoolutil/filename.h @@ -88,6 +88,8 @@ PUBLISHED: Type type = T_general); static const Filename &get_temp_directory(); + static const Filename &get_user_appdata_directory(); + static const Filename &get_common_appdata_directory(); // Assignment is via the = operator. INLINE Filename &operator = (const string &filename); @@ -222,6 +224,10 @@ protected: static bool _got_temp_directory; static Filename _temp_directory; + static bool _got_user_appdata_directory; + static Filename _user_appdata_directory; + static bool _got_common_appdata_directory; + static Filename _common_appdata_directory; public: static TypeHandle get_class_type() {