From ee137a5cedd8440441057d80b42eab4f30217bd8 Mon Sep 17 00:00:00 2001 From: rubidium Date: Wed, 13 Nov 2013 19:32:37 +0000 Subject: [PATCH] (svn r25975) -Feature [FS#5385]: XDG base directory support --- config.lib | 61 +++++++++++++++++++++++++++++++++++++++++++++ os/debian/control | 2 +- os/debian/rules | 2 +- readme.txt | 8 ++++-- src/fileio.cpp | 63 +++++++++++++++++++++++++++++++++++++---------- src/fileio_type.h | 3 +++ 6 files changed, 122 insertions(+), 17 deletions(-) diff --git a/config.lib b/config.lib index b9618f9bf6..3fefc1c833 100644 --- a/config.lib +++ b/config.lib @@ -72,6 +72,7 @@ set_default() { with_zlib="1" with_lzma="1" with_lzo2="1" + with_xdg_basedir="1" with_png="1" enable_builtin_depend="1" with_makedepend="0" @@ -145,6 +146,7 @@ set_default() { with_zlib with_lzma with_lzo2 + with_xdg_basedir with_png enable_builtin_depend with_makedepend @@ -347,6 +349,13 @@ detect_params() { --without-liblzo2) with_lzo2="0";; --with-liblzo2=*) with_lzo2="$optarg";; + --with-xdg-basedir) with_xdg_basedir="2";; + --without-xdg-basedir) with_xdg_basedir="0";; + --with-xdg-basedir=*) with_xdg_basedir="$optarg";; + --with-libxdg-basedir) with_xdg_basedir="2";; + --without-libxdg-basedir) with_xdg_basedir="0";; + --with-libxdg-basedir=*) with_xdg_basedir="$optarg";; + --with-png) with_png="2";; --without-png) with_png="0";; --with-png=*) with_png="$optarg";; @@ -818,6 +827,7 @@ check_params() { fi fi + detect_xdg_basedir detect_png detect_freetype detect_fontconfig @@ -1661,6 +1671,17 @@ make_cflags_and_ldflags() { CFLAGS="$CFLAGS -DWITH_LZO" fi + if [ -n "$xdg_basedir_config" ]; then + CFLAGS="$CFLAGS -DWITH_XDG_BASEDIR" + CFLAGS="$CFLAGS `$xdg_basedir_config --cflags | tr '\n\r' ' '`" + + if [ "$enable_static" != "0" ]; then + LIBS="$LIBS `$xdg_basedir_config --libs --static | tr '\n\r' ' '`" + else + LIBS="$LIBS `$xdg_basedir_config --libs | tr '\n\r' ' '`" + fi + fi + # 64bit machines need -D_SQ64 if [ "$cpu_type" = "64" ] && [ "$enable_universal" = "0" ]; then CFLAGS="$CFLAGS -D_SQ64" @@ -2722,6 +2743,44 @@ detect_lzma() { log 1 "checking liblzma... found" } +detect_xdg_basedir() { + # 0 means no, 1 is auto-detect, 2 is force + if [ "$with_xdg_basedir" = "0" ]; then + log 1 "checking libxdg_basedir... disabled" + + xdg_basedir_config="" + return 0 + fi + + if [ "$with_xdg_basedir" = "1" ] || [ "$with_xdg_basedir" = "" ] || [ "$with_xdg_basedir" = "2" ]; then + xdg_basedir_config="pkg-config libxdg-basedir" + else + xdg_basedir_config="$with_xdg_basedir" + fi + + version=`$xdg_basedir_config --modversion 2>/dev/null` + ret=$? + log 2 "executing $xdg_basedir_config --modversion" + log 2 " returned $version" + log 2 " exit code $ret" + + if [ -z "$version" ] || [ "$ret" != "0" ]; then + log 1 "checking libxdg_basedir... not found" + + # It was forced, so it should be found. + if [ "$with_xdg_basedir" != "1" ]; then + log 1 "configure: error: pkg-config libxdg_basedir couldn't be found" + log 1 "configure: error: you supplied '$with_xdg_basedir', but it seems invalid" + exit 1 + fi + + xdg_basedir_config="" + return 0 + fi + + log 1 "checking libxdg_basedir... found" +} + detect_png() { # 0 means no, 1 is auto-detect, 2 is force if [ "$with_png" = "0" ]; then @@ -3642,6 +3701,8 @@ showhelp() { echo " enables libfreetype support" echo " --with-fontconfig[=pkg-config fontconfig]" echo " enables fontconfig support" + echo " --with-xdg-basedir[=pkg-config libxdg-basedir]" + echo " enables fontconfig support" echo " --with-icu[=icu-config] enables icu (used for right-to-left support)" echo " --static-icu try to link statically (libsicu instead of" echo " libicu; can fail as the new name is guessed)" diff --git a/os/debian/control b/os/debian/control index de22a807ae..bfaa4cf3a4 100644 --- a/os/debian/control +++ b/os/debian/control @@ -4,7 +4,7 @@ Priority: optional Maintainer: Matthijs Kooijman Uploaders: Jordi Mallach DM-Upload-Allowed: yes -Build-Depends: debhelper (>= 7.0.50), libsdl-dev, zlib1g-dev, libpng-dev, libfreetype6-dev, libfontconfig-dev, libicu-dev, liblzma-dev, liblzo2-dev +Build-Depends: debhelper (>= 7.0.50), libsdl-dev, zlib1g-dev, libpng-dev, libfreetype6-dev, libfontconfig-dev, libicu-dev, liblzma-dev, liblzo2-dev, libxdg-basedir-dev Standards-Version: 3.8.4 Vcs-Browser: http://git.debian.org/?p=collab-maint/openttd.git Vcs-Git: git://git.debian.org/collab-maint/openttd.git diff --git a/os/debian/rules b/os/debian/rules index 97094b0c58..e2ae9db85b 100755 --- a/os/debian/rules +++ b/os/debian/rules @@ -17,7 +17,7 @@ endif # to be explicit about the dependencies, in case we're not running in a # clean build root. override_dh_auto_configure: - ./configure $(CROSS) --prefix-dir=/usr --install-dir=debian/openttd --without-allegro --with-zlib --with-sdl --with-png --with-freetype --with-fontconfig --with-icu --with-liblzo2 --with-lzma --without-iconv --disable-strip CFLAGS="$(CFLAGS) -g" LDFLAGS="$(LDFLAGS) -Wl,-as-needed" + ./configure $(CROSS) --prefix-dir=/usr --install-dir=debian/openttd --without-allegro --with-zlib --with-sdl --with-png --with-freetype --with-fontconfig --with-icu --with-liblzo2 --with-lzma --with-xdg-basedir --without-iconv --disable-strip CFLAGS="$(CFLAGS) -g" LDFLAGS="$(LDFLAGS) -Wl,-as-needed" # Do some extra installation override_dh_auto_install: diff --git a/readme.txt b/readme.txt index efec00cf95..9ff003c669 100644 --- a/readme.txt +++ b/readme.txt @@ -282,7 +282,8 @@ your operating system: C:\Documents and Settings\\My Documents\OpenTTD (2000, XP) C:\Users\\Documents\OpenTTD (Vista, 7) Mac OSX: ~/Documents/OpenTTD - Linux: ~/.openttd + Linux: $XDG_DATA_HOME/openttd which is usually ~/.local/share/openttd when + built with XDG base directory support, otherwise ~/.openttd 3. The shared directory Windows: C:\Documents and Settings\All Users\Shared Documents\OpenTTD (2000, XP) C:\Users\Public\Documents\OpenTTD (Vista, 7) @@ -322,10 +323,13 @@ Notes: others. - The previous search order is also used for NewGRFs and openttd.cfg. - If openttd.cfg is not found, then it will be created using the 2, 4, 1, 3, - 5 order. + 5 order. When built with XDG base directory support, openttd.cfg will be + created in $XDG_CONFIG_HOME/openttd which is usually ~/.config/openttd. - Savegames will be relative to the config file only if there is no save/ directory in paths with higher priority than the config file path, but autosaves and screenshots will always be relative to the config file. + Unless the configuration file is in $XDG_CONFIG_HOME/openttd, then all + other files will be saved under $XDG_DATA_HOME/openttd. The preferred setup: Place 3rd party files in shared directory (or in personal directory if you do diff --git a/src/fileio.cpp b/src/fileio.cpp index ef564aa92e..6be2195f2b 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -28,6 +28,10 @@ #include #include +#ifdef WITH_XDG_BASEDIR +#include "basedir.h" +#endif + /** Size of the #Fio data buffer. */ #define FIO_BUFFER_SIZE 512 @@ -1071,6 +1075,12 @@ bool DoScanWorkingDirectory() void DetermineBasePaths(const char *exe) { char tmp[MAX_PATH]; +#if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) + snprintf(tmp, MAX_PATH, "%s" PATHSEP "%s", xdgDataHome(NULL), + PERSONAL_DIR[0] == '.' ? &PERSONAL_DIR[1] : PERSONAL_DIR); + AppendPathSeparator(tmp, MAX_PATH); + _searchpaths[SP_PERSONAL_DIR_XDG] = strdup(tmp); +#endif #if defined(__MORPHOS__) || defined(__AMIGA__) || defined(DOS) || defined(OS2) || !defined(WITH_PERSONAL_DIR) _searchpaths[SP_PERSONAL_DIR] = NULL; #else @@ -1155,56 +1165,83 @@ void DeterminePaths(const char *exe) { DetermineBasePaths(exe); +#if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) + char config_home[MAX_PATH]; + snprintf(config_home, MAX_PATH, "%s" PATHSEP "%s", xdgConfigHome(NULL), + PERSONAL_DIR[0] == '.' ? &PERSONAL_DIR[1] : PERSONAL_DIR); + AppendPathSeparator(config_home, MAX_PATH); +#endif + Searchpath sp; FOR_ALL_SEARCHPATHS(sp) { if (sp == SP_WORKING_DIR && !_do_scan_working_directory) continue; DEBUG(misc, 4, "%s added as search path", _searchpaths[sp]); } + char *config_dir; if (_config_file != NULL) { - char *dir = strdup(_config_file); - char *end = strrchr(dir, PATHSEPCHAR); + config_dir = strdup(_config_file); + char *end = strrchr(config_dir, PATHSEPCHAR); if (end == NULL) { - dir[0] = '\0'; + config_dir[0] = '\0'; } else { end[1] = '\0'; } - _personal_dir = dir; } else { char personal_dir[MAX_PATH]; if (FioFindFullPath(personal_dir, lengthof(personal_dir), BASE_DIR, "openttd.cfg") != NULL) { char *end = strrchr(personal_dir, PATHSEPCHAR); if (end != NULL) end[1] = '\0'; - _personal_dir = strdup(personal_dir); - _config_file = str_fmt("%sopenttd.cfg", _personal_dir); + config_dir = strdup(personal_dir); + _config_file = str_fmt("%sopenttd.cfg", config_dir); } else { +#if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) + /* No previous configuration file found. Use the configuration folder from XDG. */ + config_dir = config_home; +#else static const Searchpath new_openttd_cfg_order[] = { SP_PERSONAL_DIR, SP_BINARY_DIR, SP_WORKING_DIR, SP_SHARED_DIR, SP_INSTALLATION_DIR }; for (uint i = 0; i < lengthof(new_openttd_cfg_order); i++) { if (IsValidSearchPath(new_openttd_cfg_order[i])) { - _personal_dir = strdup(_searchpaths[new_openttd_cfg_order[i]]); - _config_file = str_fmt("%sopenttd.cfg", _personal_dir); + config_dir = strdup(_searchpaths[new_openttd_cfg_order[i]]); break; } } +#endif + _config_file = str_fmt("%sopenttd.cfg", config_dir); } } - DEBUG(misc, 3, "%s found as personal directory", _personal_dir); + DEBUG(misc, 3, "%s found as config directory", config_dir); - _highscore_file = str_fmt("%shs.dat", _personal_dir); + _highscore_file = str_fmt("%shs.dat", config_dir); extern char *_hotkeys_file; - _hotkeys_file = str_fmt("%shotkeys.cfg", _personal_dir); + _hotkeys_file = str_fmt("%shotkeys.cfg", config_dir); extern char *_windows_file; - _windows_file = str_fmt("%swindows.cfg", _personal_dir); + _windows_file = str_fmt("%swindows.cfg", config_dir); + +#if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) + if (config_dir == config_home) { + /* We are using the XDG configuration home for the config file, + * then store the rest in the XDG data home folder. */ + _personal_dir = _searchpaths[SP_PERSONAL_DIR_XDG]; + FioCreateDirectory(_personal_dir); + } else +#endif + { + _personal_dir = config_dir; + } /* Make the necessary folders */ #if !defined(__MORPHOS__) && !defined(__AMIGA__) && defined(WITH_PERSONAL_DIR) - FioCreateDirectory(_personal_dir); + FioCreateDirectory(config_dir); + if (config_dir != _personal_dir) FioCreateDirectory(_personal_dir); #endif + DEBUG(misc, 3, "%s found as personal directory", _personal_dir); + static const Subdirectory default_subdirs[] = { SAVE_DIR, AUTOSAVE_DIR, SCENARIO_DIR, HEIGHTMAP_DIR, BASESET_DIR, NEWGRF_DIR, AI_DIR, AI_LIBRARY_DIR, GAME_DIR, GAME_LIBRARY_DIR, SCREENSHOT_DIR }; diff --git a/src/fileio_type.h b/src/fileio_type.h index 3f21be6dd9..87cb2d1a82 100644 --- a/src/fileio_type.h +++ b/src/fileio_type.h @@ -43,6 +43,9 @@ enum Subdirectory { enum Searchpath { SP_FIRST_DIR, SP_WORKING_DIR = SP_FIRST_DIR, ///< Search in the working directory +#if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) + SP_PERSONAL_DIR_XDG, ///< Search in the personal directory from the XDG specification +#endif SP_PERSONAL_DIR, ///< Search in the personal directory SP_SHARED_DIR, ///< Search in the shared directory, like 'Shared Files' under Windows SP_BINARY_DIR, ///< Search in the directory where the binary resides