Skip to content

Commit

Permalink
Windows: Don't store user dir prefix in the environment
Browse files Browse the repository at this point in the history
  • Loading branch information
dscharrer committed May 19, 2016
1 parent 1bb723f commit 218a5f9
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 48 deletions.
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ mark_as_advanced(
# Default runtime user and data directories
if(WIN32)
set(USER_DIR "Arx Libertatis" CACHE STRING "User dir names")
set(USER_DIR_PREFIXES "%FOLDERID_SavedGames%" CACHE STRING "User dir paths")
elseif(MACOSX)
set(DATA_DIR "ArxLibertatis" CACHE STRING "Data dir names")
set(DATA_DIR_PREFIXES "/Applications" CACHE STRING "Data dir paths")
Expand Down
9 changes: 5 additions & 4 deletions OPTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This file describes additional build options that are recognized by the CMakeLis

| Option | Windows default |
|---------------------- | ------------------------------------------------------ |
| `USER_DIR_PREFIXES` | `%FOLDERID_SavedGames%` |
| `USER_DIR_PREFIXES` | ^1 |
| `USER_DIR` | `Arx Libertatis` |
| `CONFIG_DIR_PREFIXES` | |
| `CONFIG_DIR` | |
Expand All @@ -23,7 +23,7 @@ This file describes additional build options that are recognized by the CMakeLis

| Option | Linux / BSD / other default |
|---------------------- | ------------------------------------------------------ |
| `USER_DIR_PREFIXES` | `${XDG_DATA_HOME:-$HOME/.local/share}` ^1 |
| `USER_DIR_PREFIXES` | `${XDG_DATA_HOME:-$HOME/.local/share}` ^2 |
| `USER_DIR` | `arx` |
| `CONFIG_DIR_PREFIXES` | `${XDG_CONFIG_HOME:-$HOME/.config}` |
| `CONFIG_DIR` | `arx` |
Expand All @@ -32,12 +32,13 @@ This file describes additional build options that are recognized by the CMakeLis

These pairs define prefixes and suffixes that are combined to form searched paths for the user, config and data directories respectively.

1. This matches the [XDG Base Directory Specification](http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html).
1. Arx Libertatis uses the default `Saved Games` directory (FOLDERID_SavedGames) on Windows Vista and newer, and `My Documents\My Games` on Windows XP.
2. This matches the [XDG Base Directory Specification](http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html).

To avoid possible performance issues, there is `IGNORE_EXE_DIR` to list directories to *not* search for data files even if they contain the game executable. By default, this is only set for Linux: `/usr/bin:/usr/games:/usr/games/bin:/usr/local/bin:/usr/local/games:/usr/local/games/bin`
To completely disable searching for data locations relative to the executable, set `RUNTIME_DATADIR` to an empty string.

All the configuration options above can reference environment variables in operating-system specific shell syntax which will be expanded at run-time. For Windows `%FOLDERID_SavedGames%` is defined to the Windows saved games directory for the current user.
All the configuration options above can reference environment variables in operating-system specific shell syntax which will be expanded at run-time.

After environment variable expansion the variables are interpreted as colon-separated (Windows: semicolon-separated) lists of paths.

Expand Down
46 changes: 31 additions & 15 deletions src/io/fs/SystemPaths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ static std::vector<path> getSearchPaths(const char * input) {
};

static path findUserPath(const char * name, const path & force,
const char * registry, const char * prefix,
const char * suffix, const path & fallback,
bool create) {
const char * registry, platform::SystemPathId systemPathId,
const char * prefix, const char * suffix,
const path & fallback, bool create) {

// Prefer command-line options
if(!force.empty()) {
Expand Down Expand Up @@ -97,6 +97,10 @@ static path findUserPath(const char * name, const path & force,
path to_create;
std::vector<path> prefixes = getSearchPaths(prefix);
std::vector<path> suffixes = getSearchPaths(suffix);
if(!suffixes.empty()) {
std::vector<path> paths = platform::getSystemPaths(systemPathId);
prefixes.insert(prefixes.end(), paths.begin(), paths.end());
}
bool create_exists = false;
BOOST_FOREACH(const path & prefix, prefixes) {
BOOST_FOREACH(const path & suffix, suffixes) {
Expand Down Expand Up @@ -276,20 +280,20 @@ ExitStatus SystemPaths::init() {
return init(cmdLineInitParams);
}

ExitStatus SystemPaths::init(const InitParams& initParams) {

user = findUserPath("user", initParams.forceUser, "UserDir",
ExitStatus SystemPaths::init(const InitParams & initParams) {
user = findUserPath("user", initParams.forceUser, "UserDir", platform::UserDirPrefixes,
user_dir_prefixes, user_dir, current_path(), !initParams.displaySearchDirs);

config = findUserPath("config", initParams.forceConfig, "ConfigDir",
config = findUserPath("config", initParams.forceConfig, "ConfigDir", platform::NoPath,
config_dir_prefixes, config_dir, user, !initParams.displaySearchDirs);

addData_ = initParams.dataDirs;

findData_ = initParams.findData;

data = getSearchPaths(true);

if(initParams.displaySearchDirs) {
fs::paths.list(std::cout,
" - --user-dir (-u) command-line parameter\n",
Expand Down Expand Up @@ -327,6 +331,7 @@ SystemPaths::SystemPaths()
{}

static void listDirectoriesFor(std::ostream & os, const std::string & regKey,
platform::SystemPathId systemPathId,
const char * prefixVar = NULL,
const char * suffixVar = NULL) {

Expand All @@ -345,12 +350,23 @@ static void listDirectoriesFor(std::ostream & os, const std::string & regKey,

std::vector<path> prefixes = getSearchPaths(prefixVar);
std::vector<path> suffixes = getSearchPaths(suffixVar);
if(prefixVar && suffixVar) {
std::vector<path> paths;
if(suffixVar) {
paths = platform::getSystemPaths(systemPathId);
prefixes.insert(prefixes.end(), paths.begin(), paths.end());
}
if((prefixVar || !paths.empty()) && suffixVar) {

os << " - ";
if(prefixVar) {
os << '"' << prefixVar << '"';
}
if(prefixVar && !paths.empty()) {
os << " and ";
}
if(!paths.empty()) {
os << " system paths";
}
os << " / ";
if(suffixVar) {
os << '"' << suffixVar << '"';
Expand Down Expand Up @@ -380,7 +396,7 @@ void SystemPaths::list(std::ostream & os, const std::string & forceUser,
if(!forceUser.empty()) {
os << forceUser;
}
listDirectoriesFor(os, "UserDir", user_dir_prefixes, user_dir);
listDirectoriesFor(os, "UserDir", platform::UserDirPrefixes, user_dir_prefixes, user_dir);
os << " - Current working directory\n";
os << "selected: ";
if(user.empty()) {
Expand All @@ -393,7 +409,7 @@ void SystemPaths::list(std::ostream & os, const std::string & forceUser,
if(!forceConfig.empty()) {
os << forceConfig;
}
listDirectoriesFor(os, std::string(), config_dir_prefixes, config_dir);
listDirectoriesFor(os, "ConfigDir", platform::NoPath, config_dir_prefixes, config_dir);
os << " - The selected user directory\n";
os << "selected: ";
if(config.empty()) {
Expand All @@ -410,7 +426,7 @@ void SystemPaths::list(std::ostream & os, const std::string & forceUser,
std::string exevar = getSearchPathVar(platform::getExecutablePath());
os << " - Paths specifed in \"" << exevar << "\"\n";
os << " - The directory containing the game executable\n";
listDirectoriesFor(os, "DataDir", data_dir_prefixes, data_dir);
listDirectoriesFor(os, "DataDir", platform::NoPath, data_dir_prefixes, data_dir);
os << "For all of these (except those specified via --data-dir),\n";
os << "the \"data\" subdirectory or file will also be searched.\n";
os << "selected:";
Expand Down
50 changes: 25 additions & 25 deletions src/platform/Environment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@

#include <sstream>
#include <algorithm>
#include <vector>

#include <stdlib.h> // needed for setenv, realpath and more
#include <stdlib.h> // needed for realpath and more

#include <boost/scoped_array.hpp>

Expand Down Expand Up @@ -195,22 +194,15 @@ bool getSystemConfiguration(const std::string & name, std::string & result) {
return false;
}

#if ARX_PLATFORM == ARX_PLATFORM_MACOSX

void initializeEnvironment(const char * argv0) {
ARX_UNUSED(argv0);
}

#elif ARX_PLATFORM == ARX_PLATFORM_WIN32
#if ARX_PLATFORM == ARX_PLATFORM_WIN32

// Obtain the right savegame paths for the platform
// XP is "%USERPROFILE%\My Documents\My Games"
// Vista and up : "%USERPROFILE%\Saved Games"
void initializeEnvironment(const char * argv0) {
std::vector<fs::path> getSystemPaths(SystemPathId id) {

ARX_UNUSED(argv0);
std::vector<fs::path> result;

std::basic_string<WCHAR> path;
if(id != UserDirPrefixes) {
return result;
}

// Vista and up
{
Expand All @@ -237,7 +229,7 @@ void initializeEnvironment(const char * argv0) {
HRESULT hr = GetKnownFolderPath(FOLDERID_SavedGames, kfFlagCreate | kfFlagNoAlias,
NULL, &savedgames);
if(SUCCEEDED(hr)) {
path = savedgames;
result.push_back(platform::WideString::toUTF8(savedgames));
}
CoTaskMemFree(savedgames);

Expand All @@ -255,18 +247,26 @@ void initializeEnvironment(const char * argv0) {
HRESULT hr = SHGetFolderPathW(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL,
SHGFP_TYPE_CURRENT, mydocuments);
if(SUCCEEDED(hr)) {
if(!path.empty()) {
path += L';';
}
path += mydocuments;
path += L"\\My Games";
result.push_back(fs::path(platform::WideString::toUTF8(mydocuments)) / "My Games");
}
}

if(!path.empty()) {
SetEnvironmentVariableW(L"FOLDERID_SavedGames", path.c_str());
}

return result;
}

#else

std::vector<fs::path> getSystemPaths(SystemPathId id) {
ARX_UNUSED(id);
return std::vector<fs::path>();
}

#endif

#if ARX_PLATFORM == ARX_PLATFORM_WIN32 || ARX_PLATFORM == ARX_PLATFORM_MACOSX

void initializeEnvironment(const char * argv0) {
ARX_UNUSED(argv0);
}

#else
Expand Down
18 changes: 15 additions & 3 deletions src/platform/Environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#define ARX_PLATFORM_ENVIRONMENT_H

#include <string>
#include <vector>

#include "platform/Platform.h"

Expand All @@ -31,9 +32,6 @@ namespace platform {
/*!
* \brief Initialize envirenment functions
*
* On Windows, this sets the %FOLDERID_SavedGames% environment variable to the
* standard "Saved Games" directory.
*
* \param argv0 a path to use for \ref getExecutablePath if no OS-specific function is
* available to determine the executable path. Will be ignored if it doesn't
* contain any slashes.
Expand All @@ -49,6 +47,20 @@ void initializeEnvironment(const char * argv0);
*/
std::string expandEnvironmentVariables(const std::string & in);

enum SystemPathId {
NoPath,
UserDirPrefixes //!< Directories under which to store per-user data.
};

/*!
* \brief Get a standard system path
*
* This currently does nothing on non-Windows systems.
*
* \return the path(s) or an empty string if the path is not known.
*/
std::vector<fs::path> getSystemPaths(SystemPathId path);

/*!
* \brief Get a Windows registry entry
*
Expand Down

0 comments on commit 218a5f9

Please sign in to comment.