X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=development%2FWin32%2Fpackage.C;h=fd92e5cea260f8c230fc94e706649ac41bb166ca;hb=7afbc908eb0d6d412e3e5e03fae92ca0472a76d6;hp=530342f9746b8e7fecf8c7003a4320af2c621e5a;hpb=aba840c1cbb13b21a0e91e1d337786b252c770aa;p=lyx.git diff --git a/development/Win32/package.C b/development/Win32/package.C index 530342f974..fd92e5cea2 100644 --- a/development/Win32/package.C +++ b/development/Win32/package.C @@ -19,13 +19,14 @@ #include "debug.h" #include "gettext.h" +#include "support/environment.h" #include "support/filetools.h" #include "support/lstrings.h" #include "support/os.h" #include -#include #include +#include #include #include @@ -37,6 +38,24 @@ #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 # include // SHGetFolderPath @@ -53,7 +72,6 @@ using std::string; namespace fs = boost::filesystem; - namespace lyx { namespace support { @@ -67,7 +85,8 @@ bool initialised_ = false; 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_) @@ -75,7 +94,8 @@ void init_package(string const & command_line_arg0, 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; } @@ -94,7 +114,9 @@ namespace { string const abs_path_from_binary_name(string const & exe); -std::pair const get_build_dirs(string const & abs_binary); +std::pair 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); @@ -118,7 +140,8 @@ get_user_support_dir(string const & default_user_support_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(); @@ -130,7 +153,7 @@ Package::Package(string const & command_line_arg0, // 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_ = @@ -165,20 +188,20 @@ namespace { // 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 @@ -186,7 +209,7 @@ string const hardcoded_system_support_dir() string const & Package::top_srcdir() const { - static string const dir("c:\\lyx\\lyx-devel"); + static string const dir("%TOP_SRCDIR%"); return dir; } @@ -225,7 +248,27 @@ string const win32_folder_path(int folder_id) #endif -std::pair 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 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..."; @@ -242,7 +285,7 @@ std::pair const get_build_dirs(string const & abs_binary) // 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". @@ -257,7 +300,18 @@ std::pair const get_build_dirs(string const & abs_binary) } } - 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; @@ -284,9 +338,9 @@ string const get_document_dir(string const & home_dir) 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); @@ -307,12 +361,12 @@ string const get_locale_dir(string const & system_support_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(); @@ -327,6 +381,7 @@ string const get_temp_dir() // 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"; @@ -359,7 +414,12 @@ string const abs_path_from_command_line(string const & command_line) // 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; @@ -459,7 +519,46 @@ get_system_support_dir(string const & abs_binary, 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. @@ -576,7 +675,7 @@ bool check_command_line_dir(string const & 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); } @@ -604,7 +703,7 @@ bool check_env_var_dir(string const & 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 @@ -613,7 +712,7 @@ bool check_env_var_dir(string const & dir, // translation. string const fmt = _("Invalid %1$s environment variable.\n%2$s is not a directory."); - + lyxerr << bformat(fmt, env_var, dir) << std::endl; }