X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fsupport%2FPackage.cpp;h=bdba77e7ac72780cafd97a6ad3e3b341683b6789;hb=28be7d552f62cc02fa86d7f79201d089bfb2d7b5;hp=c0a84e9a1150d05fc31f07d7db1dd21155fb1d34;hpb=788893bdea5a5c0949002c6397979c3b40c6882c;p=lyx.git diff --git a/src/support/Package.cpp b/src/support/Package.cpp index c0a84e9a11..bdba77e7ac 100644 --- a/src/support/Package.cpp +++ b/src/support/Package.cpp @@ -18,24 +18,31 @@ #include "support/ExceptionMessage.h" #include "support/filetools.h" #include "support/gettext.h" +#include "support/lassert.h" #include "support/lstrings.h" #include "support/os.h" +#include "support/PathChanger.h" +#include "support/Systemcall.h" #if defined (USE_WINDOWS_PACKAGING) # include "support/os_win32.h" #endif +#include #include #if !defined (USE_WINDOWS_PACKAGING) && \ !defined (USE_MACOSX_PACKAGING) && \ + !defined (USE_HAIKU_PACKAGING) && \ !defined (USE_POSIX_PACKAGING) -#error USE_FOO_PACKAGING must be defined for FOO = WINDOWS, MACOSX or POSIX. +#error USE_FOO_PACKAGING must be defined for FOO = WINDOWS, MACOSX, HAIKU or POSIX. #endif #if defined (USE_MACOSX_PACKAGING) -# include // FSFindFolder, FSRefMakePath +# include "support/qstring_helpers.h" +# include +# include #endif using namespace std; @@ -53,27 +60,18 @@ 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, - exe_build_dir_to_top_build_dir top_build_dir_location) + string const & command_line_user_support_dir) { - // Can do so only once. - if (initialised_) - return; - package_ = Package(command_line_arg0, command_line_system_support_dir, - command_line_user_support_dir, - top_build_dir_location); + command_line_user_support_dir); initialised_ = true; } Package const & package() { - // Commented out because package().locale_dir() can be called - // from the message translation code in Messages.cpp before - // init_package() is called. Lars is on the case... - // LASSERT(initialised_, /**/); + LAPPERR(initialised_); return package_; } @@ -82,86 +80,107 @@ namespace { FileName const abs_path_from_binary_name(string const & exe); -void buildDirs(FileName const & abs_binary, - exe_build_dir_to_top_build_dir top_build_dir_location, - FileName &, FileName &); -FileName const get_document_dir(FileName const & home_dir); +bool inBuildDir(FileName const & abs_binary, FileName &, FileName &); + +FileName findLyxBinary(FileName const & abs_binary); -FileName const get_home_dir(); +FileName const get_document_dir(FileName const & home_dir); FileName const get_locale_dir(FileName const & system_support_dir); FileName const get_system_support_dir(FileName const & abs_binary, string const & command_line_system_support_dir); -FileName const get_temp_dir(); - FileName const get_default_user_support_dir(FileName const & home_dir); bool userSupportDir(FileName const & default_user_support_dir, string const & command_line_user_support_dir, FileName & result); - string const & with_version_suffix(); +string const fix_dir_name(string const & name); + } // namespace anon Package::Package(string const & command_line_arg0, string const & command_line_system_support_dir, - string const & command_line_user_support_dir, - exe_build_dir_to_top_build_dir top_build_dir_location) + string const & command_line_user_support_dir) : explicit_user_support_dir_(false) { - home_dir_ = get_home_dir(); - system_temp_dir_ = get_temp_dir(); + // Specification of temp_dir_ may be reset by LyXRC, + // but the default is fixed for a given OS. + system_temp_dir_ = FileName::tempPath(); temp_dir_ = system_temp_dir_; - document_dir_ = get_document_dir(home_dir_); + document_dir_ = get_document_dir(get_home_dir()); FileName const abs_binary = abs_path_from_binary_name(command_line_arg0); - string const bdir = onlyPath(abs_binary.absFilename()); - // We may be using libtools - if (suffixIs(bdir, ".libs/")) - binary_dir_ = FileName(addPath(bdir, "../")); - else - binary_dir_ = FileName(bdir); + binary_dir_ = FileName(onlyPath(abs_binary.absFileName())); + + // the LyX package directory + lyx_dir_ = FileName(addPath(binary_dir_.absFileName(), "../")); + lyx_dir_ = FileName(lyx_dir_.realPath()); // Is LyX being run in-place from the build tree? - buildDirs(abs_binary, top_build_dir_location, - build_support_dir_, system_support_dir_); + in_build_dir_ = inBuildDir(abs_binary, build_support_dir_, system_support_dir_); - if (build_support_dir_.empty()) + if (!in_build_dir_) { system_support_dir_ = get_system_support_dir(abs_binary, command_line_system_support_dir); + } + + // Find the LyX executable + lyx_binary_ = findLyxBinary(abs_binary); locale_dir_ = get_locale_dir(system_support_dir_); FileName const default_user_support_dir = - get_default_user_support_dir(home_dir_); + get_default_user_support_dir(get_home_dir()); explicit_user_support_dir_ = userSupportDir(default_user_support_dir, command_line_user_support_dir, user_support_dir_); - FileName const configure_script(addName(system_support().absFilename(), "configure.py")); - configure_command_ = os::python() + ' ' + - quoteName(configure_script.toFilesystemEncoding()) + - with_version_suffix(); LYXERR(Debug::INIT, "\n" - << "\tbinary_dir " << binary_dir().absFilename() << '\n' - << "\tsystem_support " << system_support().absFilename() << '\n' - << "\tbuild_support " << build_support().absFilename() << '\n' - << "\tuser_support " << user_support().absFilename() << '\n' - << "\tlocale_dir " << locale_dir().absFilename() << '\n' - << "\tdocument_dir " << document_dir().absFilename() << '\n' - << "\ttemp_dir " << temp_dir().absFilename() << '\n' - << "\thome_dir " << home_dir().absFilename() << '\n' + << "\tbinary_dir " << binary_dir().absFileName() << '\n' + << "\tsystem_support " << system_support().absFileName() << '\n' + << "\tbuild_support " << build_support().absFileName() << '\n' + << "\tuser_support " << user_support().absFileName() << '\n' + << "\tlocale_dir " << locale_dir().absFileName() << '\n' + << "\tdocument_dir " << document_dir().absFileName() << '\n' + << "\ttemp_dir " << temp_dir().absFileName() << '\n' + << "\thome_dir " << get_home_dir().absFileName() << '\n' << "\n"); } +int Package::reconfigureUserLyXDir(string const & option) const +{ + if (configure_command_.empty()) { + FileName const configure_script(addName(system_support().absFileName(), "configure.py")); + configure_command_ = os::python() + ' ' + + quoteName(configure_script.toFilesystemEncoding()) + + with_version_suffix() + " --binary-dir=" + + quoteName(FileName(binary_dir().absFileName()).toFilesystemEncoding()); + } + + lyxerr << to_utf8(_("LyX: reconfiguring user directory")) << endl; + PathChanger p(user_support()); + Systemcall one; + int const ret = one.startscript(Systemcall::Wait, configure_command_ + option); + lyxerr << "LyX: " << to_utf8(_("Done!")) << endl; + return ret; +} + + +string Package::getConfigureLockName() const +{ + return addName(user_support().absFileName(), ".lyx_configure_lock"); +} + + void Package::set_temp_dir(FileName const & temp_dir) const { if (temp_dir.empty()) @@ -171,6 +190,35 @@ void Package::set_temp_dir(FileName const & temp_dir) const } +FileName Package::messages_file(string const & c) const +{ + if (in_build_dir_) { + FileName res = FileName(lyx_dir().absFileName() + "/../po/" + c + ".gmo"); + if (!res.isReadableFile()) + res = FileName(top_srcdir().absFileName() + "/po/" + c + ".gmo"); + return res; + } else + return FileName(locale_dir_.absFileName() + "/" + c + + "/LC_MESSAGES/" PACKAGE ".mo"); +} + + +// The specification of home_dir_ is fixed for a given OS. +// A typical example on Windows: "C:/Documents and Settings/USERNAME" +// and on a Posix-like machine: "/home/USERNAME". +FileName const & Package::get_home_dir() +{ +#if defined (USE_WINDOWS_PACKAGING) + static FileName const home_dir(getEnv("USERPROFILE")); +#elif defined (USE_MACOSX_PACKAGING) + static FileName const home_dir(fromqstr(QDir::homePath())); +#else // Posix-like. + static FileName const home_dir(getEnv("HOME")); +#endif + return home_dir; +} + + namespace { // These next functions contain the stuff that is substituted at @@ -242,24 +290,27 @@ string const fix_dir_name(string const & name) } -FileName buildSupportDir(string const & binary_dir, - exe_build_dir_to_top_build_dir top_build_dir_location) + +bool isBuildDir(FileName const & abs_binary, string const & dir_location, + FileName & build_support_dir) { - 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 FileName(addPath(binary_dir, indirection)); + string search_dir = onlyPath(abs_binary.absFileName()) + dir_location; + + // Makefile by automake + build_support_dir = FileName(addPath(search_dir, "lib")); + if (!fileSearch(build_support_dir.absFileName(), "Makefile").empty()) { + return true; + } + // cmake file, no Makefile in lib + FileName build_boost_dir = FileName(addPath(search_dir + "/3rdparty", "boost")); + if (!fileSearch(build_boost_dir.absFileName(), "cmake_install.cmake").empty()) { + return true; + } + + return false; } - -void buildDirs(FileName const & abs_binary, - exe_build_dir_to_top_build_dir top_build_dir_location, +bool inBuildDir(FileName const & abs_binary, FileName & build_support_dir, FileName & system_support_dir) { string const check_text = "Checking whether LyX is run in place..."; @@ -272,22 +323,19 @@ void buildDirs(FileName const & abs_binary, // Note that the name of the lyx binary may be a symbolic link. // If that is the case, then we follow the links too. - FileName binary = abs_binary; + FileName binary = abs_binary; while (true) { // Try and find "lyxrc.defaults". - string binary_dir = onlyPath(binary.absFilename()); - // We may be using libtools with static linking. - if (suffixIs(binary_dir, ".libs/")) - binary_dir = addPath(binary_dir, "../"); - build_support_dir = buildSupportDir(binary_dir, top_build_dir_location); - if (!fileSearch(build_support_dir.absFilename(), "Makefile").empty()) { + if( isBuildDir(binary, "../", build_support_dir) || + isBuildDir(binary, "../../", build_support_dir)) + { // Try and find "chkconfig.ltx". system_support_dir = - FileName(addPath(Package::top_srcdir().absFilename(), "lib")); + FileName(addPath(Package::top_srcdir().absFileName(), "lib")); - if (!fileSearch(system_support_dir.absFilename(), "chkconfig.ltx").empty()) { + if (!fileSearch(system_support_dir.absFileName(), "chkconfig.ltx").empty()) { LYXERR(Debug::INIT, check_text << " yes"); - return; + return true; } } @@ -308,6 +356,59 @@ void buildDirs(FileName const & abs_binary, LYXERR(Debug::INIT, check_text << " no"); system_support_dir = FileName(); build_support_dir = FileName(); + + return false; +} + + +bool doesFileExist(FileName & result, string const & search_dir, string const & name) +{ + result = fileSearch(search_dir, name); + if (!result.empty()) { + return true; + } + return false; +} + + +bool lyxBinaryPath(FileName & lyx_binary, string const & search_dir, string const & ext) +{ + lyx_binary = FileName(); + if(false) { + } else if (doesFileExist(lyx_binary, search_dir, "lyx" + ext)) { + } else if (doesFileExist(lyx_binary, search_dir, "LyX" + ext)) { + } else if (doesFileExist(lyx_binary, search_dir, "lyx" + string(PROGRAM_SUFFIX) + ext)) { + } else if (doesFileExist(lyx_binary, search_dir, "LyX" + string(PROGRAM_SUFFIX) + ext)){ + } + return !lyx_binary.empty() ? true : false; +} + + +FileName findLyxBinary(FileName const & abs_binary) +{ + string ext; + string checkname = abs_binary.toFilesystemEncoding(); + int check_len = checkname.length(); + int prgsuffixlen = string(PROGRAM_SUFFIX).length(); + if ((prgsuffixlen > 0) && (check_len > prgsuffixlen) && + (checkname.substr(check_len-prgsuffixlen) == string(PROGRAM_SUFFIX))) { + ext = ""; + } + else if (!abs_binary.extension().empty()) { + ext = "." + abs_binary.extension(); + } + + string binary_dir = onlyPath(abs_binary.absFileName()); + + FileName lyx_binary; + if (lyxBinaryPath(lyx_binary, binary_dir, ext)) + return lyx_binary; + + string search_dir = onlyPath(FileName(addPath(binary_dir, "/../")).absFileName()); + if (lyxBinaryPath(lyx_binary, search_dir, ext)) + return lyx_binary; + + return FileName(); } @@ -319,26 +420,18 @@ FileName const get_document_dir(FileName const & home_dir) (void)home_dir; // Silence warning about unused variable. os::GetFolderPath win32_folder_path; return FileName(win32_folder_path(os::GetFolderPath::PERSONAL)); +#elif defined (USE_MACOSX_PACKAGING) && (QT_VERSION >= 0x050000) + (void)home_dir; // Silence warning about unused variable. + return FileName(fromqstr(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation))); +#elif defined (USE_MACOSX_PACKAGING) + (void)home_dir; // Silence warning about unused variable. + return FileName(fromqstr(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation))); #else // Posix-like. return home_dir; #endif } -// The specification of home_dir_ is fixed for a given OS. -// A typical example on Windows: "C:/Documents and Settings/USERNAME" -// and on a Posix-like machine: "/home/USERNAME". -FileName const get_home_dir() -{ -#if defined (USE_WINDOWS_PACKAGING) - string const home_dir = getEnv("USERPROFILE"); -#else // Posix-like. - string const home_dir = getEnv("HOME"); -#endif - - return FileName(fix_dir_name(home_dir)); -} - // Several sources are probed to ascertain the locale directory. // The only requirement is that the result is indeed a directory. @@ -352,7 +445,7 @@ FileName const get_locale_dir(FileName const & system_support_dir) // 2. Search for system_support_dir / // The is OS-dependent. (On Unix, it will // be "../locale/".) - FileName path(addPath(system_support_dir.absFilename(), + FileName path(addPath(system_support_dir.absFileName(), relative_locale_dir())); if (path.exists() && path.isDirectory()) @@ -367,22 +460,6 @@ FileName const get_locale_dir(FileName const & system_support_dir) } -// Specification of temp_dir_ may be reset by LyXRC, -// but the default is fixed for a given OS. -FileName const get_temp_dir() -{ -#if defined (USE_WINDOWS_PACKAGING) - // Typical example: C:/TEMP/. - char path[MAX_PATH]; - GetTempPath(MAX_PATH, path); - // Remove trailing backslash if any. - return FileName(rtrim(to_utf8(from_local8bit(path)), "\\")); -#else // Posix-like. - return FileName("/tmp"); -#endif -} - - // Extracts the absolute path from the foo of "-sysdir foo" or "-userdir foo" FileName const abs_path_from_command_line(string const & command_line) { @@ -390,8 +467,7 @@ FileName const abs_path_from_command_line(string const & command_line) return FileName(); string const str_path = fix_dir_name(command_line); - FileName path(str_path); - return path.isAbsolute() ? path : makeAbsPath(str_path); + return makeAbsPath(str_path); } @@ -408,9 +484,8 @@ FileName const get_binary_path(string const & exe) #else string const exe_path = os::internal_path(exe); #endif - FileName exepath(exe_path); - if (exepath.isAbsolute()) - return exepath; + if (FileName::isAbsolute(exe_path)) + return FileName(exe_path); // Two possibilities present themselves. // 1. The binary is relative to the CWD. @@ -420,7 +495,7 @@ FileName const get_binary_path(string const & exe) // 2. exe must be the name of the binary only and it // can be found on the PATH. - string const exe_name = onlyFilename(exe_path); + string const exe_name = onlyFileName(exe_path); if (exe_name != exe_path) return FileName(); @@ -429,7 +504,7 @@ FileName const get_binary_path(string const & exe) vector::const_iterator const end = path.end(); for (; it != end; ++it) { // This will do nothing if *it is already absolute. - string const exe_dir = makeAbsPath(*it).absFilename(); + string const exe_dir = makeAbsPath(*it).absFileName(); FileName const exe_path(addName(exe_dir, exe_name)); if (exe_path.exists()) @@ -473,15 +548,15 @@ get_system_support_dir(FileName const & abs_binary, FileName path = abs_path_from_command_line(command_line_system_support_dir); if (!path.empty()) { searched_dirs.push_back(path); - if (check_command_line_dir(path.absFilename(), chkconfig_ltx, "-sysdir")) + if (check_command_line_dir(path.absFileName(), chkconfig_ltx, "-sysdir")) return path; } - // 2. Use the "LYX_DIR_15x" environment variable. - path = extract_env_var_dir("LYX_DIR_15x"); + // 2. Use the "LYX_DIR_${major}${minor}x" environment variable. + path = extract_env_var_dir(LYX_DIR_VER); if (!path.empty()) { searched_dirs.push_back(path); - if (check_env_var_dir(path, chkconfig_ltx, "LYX_DIR_15x")) + if (check_env_var_dir(path, chkconfig_ltx, LYX_DIR_VER)) return path; } @@ -497,12 +572,12 @@ get_system_support_dir(FileName const & abs_binary, FileName binary = abs_binary; while (true) { // Try and find "chkconfig.ltx". - string const binary_dir = onlyPath(binary.absFilename()); + string const binary_dir = onlyPath(binary.absFileName()); FileName const lyxdir(addPath(binary_dir, relative_lyxdir)); searched_dirs.push_back(lyxdir); - if (!fileSearch(lyxdir.absFilename(), chkconfig_ltx).empty()) { + if (!fileSearch(lyxdir.absFileName(), chkconfig_ltx).empty()) { // Success! "chkconfig.ltx" has been found. return lyxdir; } @@ -522,7 +597,7 @@ get_system_support_dir(FileName const & abs_binary, } // 4. Repeat the exercise on the directory itself. - FileName binary_dir(onlyPath(abs_binary.absFilename())); + FileName binary_dir(onlyPath(abs_binary.absFileName())); while (true) { // This time test whether the directory is a symbolic link // *before* looking for "chkconfig.ltx". @@ -539,11 +614,11 @@ get_system_support_dir(FileName const & abs_binary, } // Try and find "chkconfig.ltx". - FileName const lyxdir(addPath(binary_dir.absFilename(), + FileName const lyxdir(addPath(binary_dir.absFileName(), relative_lyxdir)); searched_dirs.push_back(lyxdir); - if (!fileSearch(lyxdir.absFilename(), chkconfig_ltx).empty()) { + if (!fileSearch(lyxdir.absFileName(), chkconfig_ltx).empty()) { // Success! "chkconfig.ltx" has been found. return lyxdir; } @@ -551,7 +626,7 @@ get_system_support_dir(FileName const & abs_binary, // 5. In desparation, try the hard-coded system support dir. path = hardcoded_system_support_dir(); - if (!fileSearch(path.absFilename(), chkconfig_ltx).empty()) + if (!fileSearch(path.absFileName(), chkconfig_ltx).empty()) return path; // Everything has failed :-( @@ -563,22 +638,19 @@ get_system_support_dir(FileName const & abs_binary, for (iterator it = begin; it != end; ++it) { if (it != begin) searched_dirs_str += "\n\t"; - searched_dirs_str += it->absFilename(); + searched_dirs_str += it->absFileName(); } // FIXME UNICODE throw ExceptionMessage(ErrorException, _("No system directory"), bformat(_("Unable to determine the system directory " - "having searched\n" - "\t%1$s\n" - "Use the '-sysdir' command line parameter or " - "set the environment variable LYX_DIR_15x to " - "the LyX system directory containing the file " - "`chkconfig.ltx'."), - from_utf8(searched_dirs_str))); - - // Keep the compiler happy. - return FileName(); + "having searched\n" + "\t%1$s\n" + "Use the '-sysdir' command line parameter or " + "set the environment variable\n%2$s " + "to the LyX system directory containing the " + "file `chkconfig.ltx'."), + from_utf8(searched_dirs_str), from_ascii(LYX_DIR_VER))); } @@ -593,8 +665,8 @@ bool userSupportDir(FileName const & default_user_support_dir, if (!result.empty()) return true; - // 2. Use the LYX_USERDIR_15x environment variable. - result = extract_env_var_dir("LYX_USERDIR_15x"); + // 2. Use the LYX_USERDIR_${major}${minor}x environment variable. + result = extract_env_var_dir(LYX_USERDIR_VER); if (!result.empty()) return true; @@ -614,28 +686,19 @@ FileName const get_default_user_support_dir(FileName const & home_dir) os::GetFolderPath win32_folder_path; return FileName(addPath(win32_folder_path(os::GetFolderPath::APPDATA), PACKAGE)); -#elif defined (USE_MACOSX_PACKAGING) +#elif defined (USE_MACOSX_PACKAGING) && (QT_VERSION >= 0x050000) (void)home_dir; // Silence warning about unused variable. + return FileName(addPath(fromqstr(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)), PACKAGE)); - FSRef fsref; - OSErr const error_code = - FSFindFolder(kUserDomain, kApplicationSupportFolderType, - kDontCreateFolder, &fsref); - if (error_code != 0) - return FileName(); - - // FSRefMakePath returns the result in utf8 - char store[PATH_MAX + 1]; - OSStatus const status_code = - FSRefMakePath(&fsref, - reinterpret_cast(store), PATH_MAX); - if (status_code != 0) - return FileName(); +#elif defined (USE_MACOSX_PACKAGING) + (void)home_dir; // Silence warning about unused variable. + return FileName(addPath(fromqstr(QDesktopServices::storageLocation(QDesktopServices::DataLocation)), PACKAGE)); - return FileName(addPath(reinterpret_cast(store), PACKAGE)); +#elif defined (USE_HAIKU_PACKAGING) + return FileName(addPath(home_dir.absFileName(), string("/config/settings/") + PACKAGE)); #else // USE_POSIX_PACKAGING - return FileName(addPath(home_dir.absFilename(), string(".") + PACKAGE)); + return FileName(addPath(home_dir.absFileName(), string(".") + PACKAGE)); #endif } @@ -673,13 +736,13 @@ bool check_env_var_dir(FileName const & dir, string const & file, string const & env_var) { - FileName const abs_path = fileSearch(dir.absFilename(), file); + FileName const abs_path = fileSearch(dir.absFileName(), file); if (abs_path.empty()) { // FIXME UNICODE throw ExceptionMessage(WarningException, _("File not found"), bformat( _("Invalid %1$s environment variable.\n" "Directory %2$s does not contain %3$s."), - from_utf8(env_var), from_utf8(dir.absFilename()), + from_utf8(env_var), from_utf8(dir.absFileName()), from_utf8(file))); } @@ -704,7 +767,7 @@ bool check_env_var_dir(FileName const & dir, _("Invalid %1$s environment variable.\n%2$s is not a directory."); throw ExceptionMessage(WarningException, _("Directory not found"), bformat( - fmt, from_utf8(env_var), from_utf8(dir.absFilename()))); + fmt, from_utf8(env_var), from_utf8(dir.absFileName()))); } return success;