#include "debug.h"
#include "gettext.h"
+#include "support/environment.h"
#include "support/filetools.h"
#include "support/lstrings.h"
#include "support/os.h"
#include <boost/assert.hpp>
-#include <boost/tuple/tuple.hpp>
#include <boost/filesystem/operations.hpp>
+#include <boost/tuple/tuple.hpp>
#include <list>
#include <utility>
#endif
#if defined (USE_WINDOWS_PACKAGING)
+
+/*
+ * MinGW's version of winver.h contains this comment:
+ *
+ * If you need Win32 API features newer the Win95 and WinNT then you must
+ * define WINVER before including windows.h or any other method of including
+ * the windef.h header.
+ *
+ * GetLongPathNameA requires WINVER == 0x0500.
+ *
+ * It doesn't matter if the Windows version is older than this because the
+ * function will compile but will fail at run time. See
+ * http://msdn.microsoft.com/library/en-us/mslu/winprog/microsoft_layer_for_unicode_apis_with_limited_support.asp
+ */
+# if defined(__MINGW32__)
+# define WINVER 0x0500
+# endif
+
# include <windows.h>
# include <shlobj.h> // SHGetFolderPath
namespace fs = boost::filesystem;
-
namespace lyx {
namespace support {
void init_package(string const & command_line_arg0,
string const & command_line_system_support_dir,
- string const & command_line_user_support_dir)
+ string const & command_line_user_support_dir,
+ exe_build_dir_to_top_build_dir top_build_dir_location)
{
// Can do so only once.
if (initialised_)
package_ = Package(command_line_arg0,
command_line_system_support_dir,
- command_line_user_support_dir);
+ command_line_user_support_dir,
+ top_build_dir_location);
initialised_ = true;
}
string const abs_path_from_binary_name(string const & exe);
-std::pair<string, string> const get_build_dirs(string const & abs_binary);
+std::pair<string, string> const
+get_build_dirs(string const & abs_binary,
+ exe_build_dir_to_top_build_dir top_build_dir_location);
string const get_document_dir(string const & home_dir);
Package::Package(string const & command_line_arg0,
string const & command_line_system_support_dir,
- string const & command_line_user_support_dir)
+ string const & command_line_user_support_dir,
+ exe_build_dir_to_top_build_dir top_build_dir_location)
: explicit_user_support_dir_(false)
{
home_dir_ = get_home_dir();
// Is LyX being run in-place from the build tree?
boost::tie(build_support_dir_, system_support_dir_) =
- get_build_dirs(abs_binary);
+ get_build_dirs(abs_binary, top_build_dir_location);
if (build_support_dir_.empty())
system_support_dir_ =
// configuration-time.
string const top_srcdir()
{
- static string const dir("c:\\lyx\\lyx-devel");
+ static string const dir("%TOP_SRCDIR%");
return dir;
}
string const hardcoded_localedir()
{
- return string("c:\\lyx\\lyx-devel\\lib\\locale");
+ return string("%LOCALEDIR%");
}
string const hardcoded_system_support_dir()
{
- return string("c:\\lyx\\lyx-devel\\lib");
+ return string("../../lib/");
}
} // namespace anon
string const & Package::top_srcdir() const
{
- static string const dir("c:\\lyx\\lyx-devel");
+ static string const dir("%TOP_SRCDIR%");
return dir;
}
#endif
-std::pair<string, string> const get_build_dirs(string const & abs_binary)
+std::string const
+get_build_support_dir(std::string const & binary_dir,
+ exe_build_dir_to_top_build_dir top_build_dir_location)
+{
+ string indirection;
+ switch (top_build_dir_location) {
+ case top_build_dir_is_one_level_up:
+ indirection = "../lib";
+ break;
+ case top_build_dir_is_two_levels_up:
+ indirection = "../../lib";
+ break;
+ }
+
+ return NormalizePath(AddPath(binary_dir, indirection));
+}
+
+
+std::pair<string, string> const
+get_build_dirs(string const & abs_binary,
+ exe_build_dir_to_top_build_dir top_build_dir_location)
{
string const check_text = "Checking whether LyX is run in place...";
// Try and find "lyxrc.defaults".
string const binary_dir = OnlyPath(binary);
string const build_support_dir =
- NormalizePath(AddPath(binary_dir, "../lib"));
+ get_build_support_dir(binary_dir, top_build_dir_location);
if (!FileSearch(build_support_dir, "lyxrc.defaults").empty()) {
// Try and find "chkconfig.ltx".
}
}
- break;
+ // Check whether binary is a symbolic link.
+ // If so, resolve it and repeat the exercise.
+ if (!fs::symbolic_link_exists(binary))
+ break;
+
+ string link;
+ if (LyXReadLink(binary, link, true)) {
+ binary = link;
+ } else {
+ // Unable to resolve the link.
+ break;
+ }
}
lyxerr[Debug::INIT] << check_text << " no" << std::endl;
string const get_home_dir()
{
#if defined (USE_WINDOWS_PACKAGING)
- string const home_dir = GetEnv("USERPROFILE");
+ string const home_dir = getEnv("USERPROFILE");
#else // Posix-like.
- string const home_dir = GetEnv("HOME");
+ string const home_dir = getEnv("HOME");
#endif
return os::internal_path(home_dir);
// be "../locale/".)
path = NormalizePath(AddPath(system_support_dir, relative_locale_dir()));
- if (fs::is_directory(path))
+ if (fs::exists(path) && fs::is_directory(path))
return path;
// 3. Fall back to the hard-coded LOCALEDIR.
path = hardcoded_localedir();
- if (fs::is_directory(path))
+ if (fs::exists(path) && fs::is_directory(path))
return path;
return string();
// Typical example: C:/TEMP/.
char path[MAX_PATH + 1];
GetTempPath(MAX_PATH, path);
+ GetLongPathName(path, path, MAX_PATH + 1);
return os::internal_path(path);
#else // Posix-like.
return "/tmp";
// Does the grunt work for abs_path_from_binary_name()
string const get_binary_path(string const & exe)
{
- string const exe_path = os::internal_path(exe);
+ // The executable may have been invoked either with or
+ // without the .exe extension.
+ // Ensure that it is present.
+ string const as_internal_path = os::internal_path(exe);
+ string const exe_path = suffixIs(as_internal_path, ".exe") ?
+ as_internal_path : as_internal_path + ".exe";
if (os::is_absolute_path(exe_path))
return exe_path;
return lyxdir;
}
- break;
+ // Check whether binary is a symbolic link.
+ // If so, resolve it and repeat the exercise.
+ if (!fs::symbolic_link_exists(binary))
+ break;
+
+ string link;
+ if (LyXReadLink(binary, link, true)) {
+ binary = link;
+ } else {
+ // Unable to resolve the link.
+ break;
+ }
+ }
+
+ // 4. Repeat the exercise on the directory itself.
+ string binary_dir = OnlyPath(abs_binary);
+ while (true) {
+ // This time test whether the directory is a symbolic link
+ // *before* looking for "chkconfig.ltx".
+ // (We've looked relative to the original already.)
+ if (!fs::symbolic_link_exists(binary))
+ break;
+
+ string link;
+ if (LyXReadLink(binary_dir, link, true)) {
+ binary_dir = link;
+ } else {
+ // Unable to resolve the link.
+ break;
+ }
+
+ // Try and find "chkconfig.ltx".
+ string const lyxdir =
+ NormalizePath(AddPath(binary_dir, relative_lyxdir));
+ searched_dirs.push_back(lyxdir);
+
+ if (!FileSearch(lyxdir, chkconfig_ltx).empty()) {
+ // Success! "chkconfig.ltx" has been found.
+ return lyxdir;
+ }
}
// 5. In desparation, try the hard-coded system support dir.
// The environment variable @c env_var expands to a (single) file path.
string const extract_env_var_dir(string const & env_var)
{
- string const dir = os::internal_path(GetEnv(env_var));
+ string const dir = os::internal_path(getEnv(env_var));
return dir.empty() ? dir : MakeAbsPath(dir);
}
bool check_env_var_dir(string const & dir,
string const & env_var)
{
- bool const success = fs::is_directory(dir);
+ bool const success = (fs::exists(dir) && fs::is_directory(dir));
if (!success) {
// Put this string on a single line so that the gettext
// translation.
string const fmt =
_("Invalid %1$s environment variable.\n%2$s is not a directory.");
-
+
lyxerr << bformat(fmt, env_var, dir)
<< std::endl;
}