From: André Pönitz Date: Mon, 27 Aug 2007 21:29:56 +0000 (+0000) Subject: remove special handling of Package.cpp[.in] X-Git-Tag: 1.6.10~8674 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=d65a564adfbfa098fbb22026559461df9186746a;p=features.git remove special handling of Package.cpp[.in] git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@19840 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/configure.ac b/configure.ac index 5d2650036a..39d2292e7d 100644 --- a/configure.ac +++ b/configure.ac @@ -312,19 +312,12 @@ ${FRONTEND_INFO}\ LyX binary dir: ${real_bindir}\n\ LyX files dir: ${real_pkgdatadir}\n" -MSYS_AC_CANONICAL_PATH(LYX_ABS_TOP_SRCDIR, ${srcdir}) -MSYS_AC_CANONICAL_PATH(LYX_ABS_INSTALLED_LOCALEDIR, ${real_localedir}) -MSYS_AC_CANONICAL_PATH(LYX_ABS_INSTALLED_DATADIR, ${real_pkgdatadir}) - AC_SUBST(VERSION_INFO) AC_SUBST(RPM_FRONTEND) AC_SUBST(AM_CPPFLAGS) AC_SUBST(AM_CXXFLAGS) AC_SUBST(AM_CFLAGS) AC_SUBST(AM_LDFLAGS) -AC_SUBST(LYX_ABS_TOP_SRCDIR) -AC_SUBST(LYX_ABS_INSTALLED_LOCALEDIR) -AC_SUBST(LYX_ABS_INSTALLED_DATADIR) ## Some config.h stuff @@ -454,6 +447,19 @@ AC_ARG_ENABLE(monolithic-frontend-qt4, [enable_monolithic_frontend_qt4=no]) AM_CONDITIONAL(MONOLITHIC_FRONTEND_QT4, test "$enable_monolithic_frontend_qt4" = "yes") +MSYS_AC_CANONICAL_PATH(lyx_abs_top_srcdir, ${srcdir}) +MSYS_AC_CANONICAL_PATH(lyx_abs_installed_localedir, ${real_localedir}) +MSYS_AC_CANONICAL_PATH(lyx_abs_installed_datadir, ${real_pkgdatadir}) + +AC_DEFINE_UNQUOTED([LYX_ABS_TOP_SRCDIR], + "${lyx_abs_top_srcdir}", [Top source directory]) +AC_DEFINE_UNQUOTED([LYX_ABS_INSTALLED_LOCALEDIR], + "${lyx_abs_installed_localedir}",[Hard coded locale directory]) +AC_DEFINE_UNQUOTED([LYX_ABS_INSTALLED_DATADIR], + "${lyx_abs_installed_datadir}",[Hard system support directory]) +AC_DEFINE_UNQUOTED([PROGRAM_SUFFIX], + "${version_suffix}",[Program version suffix]) + AC_DEFINE_UNQUOTED([LYX_DATE],"$LYX_DATE",[Date of release]) AC_DEFINE_UNQUOTED([VERSION_INFO],"$VERSION_INFO",[Full version info]) AC_DEFINE_UNQUOTED([LYX_MAJOR_VERSION],$lyx_major,[Major version number]) @@ -461,7 +467,6 @@ AC_DEFINE_UNQUOTED([LYX_MINOR_VERSION],$lyx_minor,[Minor version number]) AC_DEFINE_UNQUOTED([LYX_RELEASE_LEVEL],$lyx_release,[Release version number]) AC_DEFINE_UNQUOTED([LYX_RELEASE_PATCH],$lyx_patch,[Patch version number]) - AC_CONFIG_FILES([Makefile boost/Makefile \ config/Makefile \ @@ -472,7 +477,7 @@ AC_CONFIG_FILES([Makefile development/MacOSX/spotlight/Makefile \ development/lyx.spec \ intl/Makefile \ - lib/Makefile \ + lib/Makefile \ lib/doc/Makefile \ lib/lyx2lyx/lyx2lyx_version.py \ lib/lyx2lyx/Makefile \ diff --git a/development/cmake/config.h.cmake b/development/cmake/config.h.cmake index 55da8fa750..8f15e9ff55 100644 --- a/development/cmake/config.h.cmake +++ b/development/cmake/config.h.cmake @@ -116,6 +116,10 @@ #cmakedefine LYX_DATE "${LYX_DATE}" #cmakedefine VERSION_INFO "${VERSION_INFO}" +#cmakedefine PROGRAM_SUFFIX "${PPROGRAM_SUFFIX}" +#cmakedefine LYX_ABS_INSTALLED_DATADIR "${LYX_DIR}" +#cmakedefine LYX_ABS_INSTALLED_LOCALEDIR "${LOCALEDIR}" +#cmakedefine LYX_ABS_TOP_SRCDIR "${TOP_SRCDIR}" #cmakedefine USE_POSIX_PACKAGING 1 #cmakedefine USE_WINDOWS_PACKAGING 1 diff --git a/development/cmake/src/support/CMakeLists.txt b/development/cmake/src/support/CMakeLists.txt index 0221d64d67..594af5dcc0 100644 --- a/development/cmake/src/support/CMakeLists.txt +++ b/development/cmake/src/support/CMakeLists.txt @@ -6,8 +6,8 @@ project(support) -configure_file(${TOP_SRC_DIR}/src/support/Package.cpp.in - ${CMAKE_CURRENT_BINARY_DIR}/package.C) +#configure_file(${TOP_SRC_DIR}/src/support/Package.cpp.in +# ${CMAKE_CURRENT_BINARY_DIR}/package.C) file(GLOB support_sources ${TOP_SRC_DIR}/src/support/${LYX_CPP_FILES}) file(GLOB support_headers ${TOP_SRC_DIR}/src/support/${LYX_HPP_FILES}) @@ -25,7 +25,7 @@ list(REMOVE_ITEM support_sources ${TOP_SRC_DIR}/src/support/minizip/iowin32.h ${TOP_SRC_DIR}/src/support/minizip/iowin32.c) -set(support_sources ${support_sources} ${CMAKE_CURRENT_BINARY_DIR}/package.C) +#set(support_sources ${support_sources} ${CMAKE_CURRENT_BINARY_DIR}/package.C) lyx_add_msvc_pch(support) diff --git a/development/qmake/app/app.pro b/development/qmake/app/app.pro index 626f566204..791a07a41c 100644 --- a/development/qmake/app/app.pro +++ b/development/qmake/app/app.pro @@ -21,7 +21,6 @@ LIBS += -lAiksaurus LIBS += -L../lib -LIBS += ../support/$(OBJECTS_DIR)/Package.o LIBS += -Wl,--start-group LIBS += -llyxmathed$${DEBUGSUFFIX} LIBS += -llyxinsets$${DEBUGSUFFIX} diff --git a/development/qmake/support/support.pro b/development/qmake/support/support.pro index d4dcf9a4ae..ca5318ad57 100644 --- a/development/qmake/support/support.pro +++ b/development/qmake/support/support.pro @@ -55,6 +55,7 @@ CPP += FileName.cpp CPP += ForkedCallQueue.cpp CPP += Forkedcall.cpp CPP += ForkedcallsController.cpp +CPP += Package.cpp CPP += Path.cpp CPP += Systemcall.cpp CPP += Timeout.cpp @@ -84,63 +85,6 @@ CPP += unicode.cpp CPP += unlink.cpp CPP += userinfo.cpp - -QMAKE_RUN_CXX1 = $(CXX) -c $(CXXFLAGS) $(INCPATH) - -#packagetarget.target = Package.cpp -#packagetarget.commands = \ -# @rm -f tmp_package ;\ -# sed \'s,@LYX_DIR@,$(LYX_ABS_INSTALLED_DATADIR),;\ -#s,@LOCALEDIR@,$(LYX_ABS_INSTALLED_LOCALEDIR),;\ -#s,@TOP_SRCDIR@,$(LYX_ABS_TOP_SRCDIR),;\ -#s,@PROGRAM_SUFFIX@,$(program_suffix),\' \ -# $${BUILD_BASE_SOURCE_DIR}/src/support/Package.cpp.in > tmp_package ;\ -# if cmp -s tmp_package Package.cpp ; then \ -# rm -f tmp_package ;\ -# else \ -# rm -f Package.cpp ;\ -# cp tmp_package Package.cpp ;\ -# fi -#packagetarget.depends = config.h -#packagetarget.variable_out = SOURCES -#packagetarget.CONFIG = no_link -##SOURCES += $${BUILD_BASE_TARGET_DIR}/src/Package.cpp -#QMAKE_EXTRA_TARGETS += packagetarget -# -##OBJECTS += $(OBJECTS_DIR)/Package.o -#POST_TARGETDEPS += $(OBJECTS_DIR)/Package.o - -packagetarget.target = Package.cpp -packagetarget.commands = \ - @rm -f tmp_package ;\ - sed \'s,@LYX_DIR@,$(LYX_ABS_INSTALLED_DATADIR),;\ -s,@LOCALEDIR@,$(LYX_ABS_INSTALLED_LOCALEDIR),;\ -s,@TOP_SRCDIR@,$(LYX_ABS_TOP_SRCDIR),;\ -s,@PROGRAM_SUFFIX@,$(program_suffix),\' \ - $${BUILD_BASE_SOURCE_DIR}/src/support/Package.cpp.in > tmp_package ;\ - if cmp -s tmp_package Package.cpp ; then \ - rm -f tmp_package ;\ - else \ - rm -f Package.cpp ;\ - cp tmp_package Package.cpp ;\ - fi -#packagetarget.depends = config.h -packagetarget.CONFIG = no_link -#SOURCES += $${BUILD_BASE_TARGET_DIR}/src/Package.cpp - -packagetarget2.target = $(OBJECTS_DIR)/Package.o -packagetarget2.commands = $${QMAKE_RUN_CXX1} -c Package.cpp \ - -o $(OBJECTS_DIR)/Package.o -packagetarget2.depends = Package.cpp - -QMAKE_EXTRA_TARGETS += packagetarget packagetarget2 - -QMAKE_CLEAN += $(OBJECTS_DIR)/Package.o Package.cpp - -PRE_TARGETDEPS += $(OBJECTS_DIR)/Package.o - -LIBS += $(OBJECTS_DIR)/Package.o - for(FILE,CPP) { SOURCES += $${BUILD_BASE_SOURCE_DIR}/src/support/$${FILE} } for(FILE,HPP) { HEADERS += $${BUILD_BASE_SOURCE_DIR}/src/support/$${FILE} } for(PATH,INC) { INCLUDEPATH += $${BUILD_BASE_SOURCE_DIR}/$${PATH} } diff --git a/development/scons/SConstruct b/development/scons/SConstruct index b07cd0e5aa..e66633e5c3 100644 --- a/development/scons/SConstruct +++ b/development/scons/SConstruct @@ -350,10 +350,11 @@ env.AppendUnique(LIBPATH = ['$LOCALLIBPATH']) # 3. compiler commands and flags like CCFLAGS. # MSGFMT used to process po files # 4. Variables that will be used to replace variables in some_file.in -# src/support/Package.cpp.in: -# TOP_SRCDIR, LOCALEDIR, LYX_DIR, PROGRAM_SUFFIX # lib/lyx2lyx/lyx2lyx_version.py.in # PACKAGE_VERSION +# FIXME Bo: Please look here, that's not needed anymore (Andre') +# src/support/Package.cpp.in: +# TOP_SRCDIR, LOCALEDIR, LYX_DIR, PROGRAM_SUFFIX # full path name is used to build msvs project files # and to replace TOP_SRCDIR in package.C @@ -383,6 +384,8 @@ if env.has_key('version_suffix'): program_suffix = env['version_suffix'] else: program_suffix = '' + +# FIXME Bo: Please look here, can this be simplified? (Andre') # used by Package.cpp.in env['PROGRAM_SUFFIX'] = program_suffix @@ -1042,6 +1045,14 @@ result = utils.createConfigFile(conf, 'Full version info'), ('#define LYX_DATE "%s"' % lyx_date, 'Date of release'), + ('#define PROGRAM_SUFFIX "%s"' % '$PROGRAM_SUFFIX', + 'Program version suffix'), + ('#define LYX_ABS_INSTALLED_DATADIR "%s"' % '$LYX_DIR', + 'Hard coded system support directory'), + ('#define LYX_ABS_INSTALLED_LOCALEDIR "%s"' % '$LOCALEDIR', + 'Hard coded locale directory'), + ('#define LYX_ABS_TOP_SRCDIR "%s"' % '$TOP_SRCDIR', + 'Top source directory'), ('#define BOOST_ALL_NO_LIB 1', 'disable automatic linking of boost libraries.'), ('#define USE_%s_PACKAGING 1' % packaging_method.upper(), diff --git a/development/scons/scons_manifest.py b/development/scons/scons_manifest.py index 46b1ce039f..d57cec9741 100644 --- a/development/scons/scons_manifest.py +++ b/development/scons/scons_manifest.py @@ -340,6 +340,7 @@ src_support_files = Split(''' ForkedCallQueue.cpp Forkedcall.cpp ForkedcallsController.cpp + Package.cpp Path.cpp Systemcall.cpp Timeout.cpp @@ -377,7 +378,6 @@ src_support_extra_header_files = Split(''' src_support_extra_src_files = Split(''' - Package.cpp.in atexit.c os_cygwin.cpp os_unix.cpp diff --git a/po/POTFILES.in b/po/POTFILES.in index db9f98e49e..e0c0538533 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -32,7 +32,6 @@ src/callback.cpp src/client/debug.cpp src/debug.cpp src/frontends/LyXView.cpp -src/frontends/WorkArea.cpp src/frontends/controllers/ControlAboutlyx.cpp src/frontends/controllers/ControlBibtex.cpp src/frontends/controllers/ControlBox.cpp @@ -144,7 +143,6 @@ src/output.cpp src/output_plaintext.cpp src/rowpainter.cpp src/support/FileFilterList.cpp -src/support/Package.cpp.in src/support/filetools.cpp src/support/os_win32.cpp src/support/userinfo.cpp diff --git a/src/support/Makefile.am b/src/support/Makefile.am index e26d035a6b..1692e9fa60 100644 --- a/src/support/Makefile.am +++ b/src/support/Makefile.am @@ -2,7 +2,7 @@ include $(top_srcdir)/config/common.am CLEANFILES += $(BUILT_SOURCES) -EXTRA_DIST = Package.cpp.in pch.h \ +EXTRA_DIST = pch.h \ os_cygwin.cpp os_unix.cpp os_win32.cpp os_win32.h pkglib_LTLIBRARIES = liblyxsupport.la @@ -10,7 +10,7 @@ pkglib_LTLIBRARIES = liblyxsupport.la liblyxsupport_la_LIBADD = $(LIBSHLWAPI) $(QT4_CORE_LIB) $(BOOST_SIGNALS) liblyxsupport_la_LDFLAGS = $(QT4_CORE_LDFLAGS) -BUILT_SOURCES = $(PCH_FILE) Package.cpp +BUILT_SOURCES = $(PCH_FILE) AM_CPPFLAGS += $(PCH_FLAGS) -I$(srcdir)/.. $(BOOST_INCLUDES) AM_CPPFLAGS += $(QT4_CPPFLAGS) $(QT4_CORE_INCLUDES) -I$(srcdir)/minizip @@ -103,24 +103,6 @@ liblyxsupport_la_SOURCES = \ minizip/zip.c \ minizip/zip.h -Package.cpp: build_package - -# Solaris sed does not like spaces bewteen the ;-delimited commands -build_package: Package.cpp.in - @rm -f tmp_package ;\ - sed "s,@LYX_DIR@,$(LYX_ABS_INSTALLED_DATADIR),;\ -s,@LOCALEDIR@,$(LYX_ABS_INSTALLED_LOCALEDIR),;\ -s,@TOP_SRCDIR@,$(LYX_ABS_TOP_SRCDIR),;\ -s,@PROGRAM_SUFFIX@,$(program_suffix)," \ - $(srcdir)/Package.cpp.in > tmp_package ;\ - if cmp -s tmp_package Package.cpp ; then \ - rm -f tmp_package ;\ - else \ - rm -f Package.cpp ;\ - mv tmp_package Package.cpp ;\ - fi - - ############################## Tests ################################## EXTRA_DIST += tests/test_convert tests/test_filetools \ diff --git a/src/support/Package.cpp b/src/support/Package.cpp new file mode 100644 index 0000000000..3535f7a625 --- /dev/null +++ b/src/support/Package.cpp @@ -0,0 +1,748 @@ +// -*- C++ -*- +/** + * \file package.C + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Angus Leeming + * + * Full author contact details are available in file CREDITS. + */ + +#include + +#include "support/Package.h" + +#include "debug.h" +#include "gettext.h" + +#include "support/environment.h" +#include "support/filetools.h" +#include "support/lstrings.h" +#include "support/ExceptionMessage.h" +#include "support/os.h" + +#if defined (USE_WINDOWS_PACKAGING) +# include "support/os_win32.h" +#endif + +#include +#include + +#include +#include + +#if !defined (USE_WINDOWS_PACKAGING) && \ + !defined (USE_MACOSX_PACKAGING) && \ + !defined (USE_POSIX_PACKAGING) +#error USE_FOO_PACKAGING must be defined for FOO = WINDOWS, MACOSX or POSIX. +#endif + +#if defined (USE_MACOSX_PACKAGING) +# include // FSFindFolder, FSRefMakePath +#endif + +using std::string; + +namespace fs = boost::filesystem; + +namespace lyx { +namespace support { + +namespace { + +Package package_; +bool initialised_ = false; + +} // namespace anon + + +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) +{ + // 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); + 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... + // BOOST_ASSERT(initialised_); + return package_; +} + + +namespace { + +FileName const abs_path_from_binary_name(string const & exe); + +std::pair const +get_build_dirs(FileName const & abs_binary, + exe_build_dir_to_top_build_dir top_build_dir_location); + +FileName const get_document_dir(FileName const & home_dir); + +FileName const get_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); + +std::pair const +get_user_support_dir(FileName const & default_user_support_dir, + string const & command_line_user_support_dir); + + +string const & with_version_suffix(); + +} // 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) + : explicit_user_support_dir_(false) +{ + home_dir_ = get_home_dir(); + system_temp_dir_ = get_temp_dir(); + temp_dir_ = system_temp_dir_; + document_dir_ = get_document_dir(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); + + // Is LyX being run in-place from the build tree? + boost::tie(build_support_dir_, system_support_dir_) = + get_build_dirs(abs_binary, top_build_dir_location); + + if (build_support_dir_.empty()) + system_support_dir_ = + get_system_support_dir(abs_binary, + command_line_system_support_dir); + + locale_dir_ = get_locale_dir(system_support_dir_); + + FileName const default_user_support_dir = + get_default_user_support_dir(home_dir_); + boost::tie(user_support_dir_, explicit_user_support_dir_) = + get_user_support_dir(default_user_support_dir, + command_line_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' + << "\n" << std::endl; +} + + +namespace { + +// These next functions contain the stuff that is substituted at +// configuration-time. +FileName const hardcoded_localedir() +{ + // FIXME UNICODE + // The build system needs to make sure that this is in utf8 encoding. + return FileName(LYX_ABS_INSTALLED_LOCALEDIR); +} + + +FileName const hardcoded_system_support_dir() +{ + // FIXME UNICODE + // The build system needs to make sure that this is in utf8 encoding. + return FileName(LYX_ABS_INSTALLED_DATADIR); +} + + +string const & with_version_suffix() +{ + static string const program_suffix = PROGRAM_SUFFIX; + static string const with_version_suffix = + " --with-version-suffix=" PROGRAM_SUFFIX; + return program_suffix.empty() ? program_suffix : with_version_suffix; +} + +} // namespace anon + + +FileName const & Package::top_srcdir() +{ + // FIXME UNICODE + // The build system needs to make sure that this is in utf8 encoding. + static FileName const dir(LYX_ABS_TOP_SRCDIR); + return dir; +} + + +namespace { + +bool check_command_line_dir(string const & dir, + string const & file, + string const & command_line_switch); + +FileName const extract_env_var_dir(string const & env_var); + +bool check_env_var_dir(FileName const & dir, + string const & env_var); + +bool check_env_var_dir(FileName const & dir, + string const & file, + string const & env_var); + +string const relative_locale_dir(); + +string const relative_system_support_dir(); + + +/** + * Convert \p name to internal path and strip a trailing slash, since it + * comes from user input (commandline or environment). + * \p name is encoded in utf8. + */ +string const fix_dir_name(string const & name) +{ + return rtrim(os::internal_path(name), "/"); +} + + +FileName const +get_build_support_dir(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 FileName(normalizePath(addPath(binary_dir, indirection))); +} + + +std::pair const +get_build_dirs(FileName 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..."; + + // We're looking for "Makefile" in a directory + // binary_dir/../lib + // We're also looking for "chkconfig.ltx" in a directory + // top_srcdir()/lib + // If both are found, then we're running LyX in-place. + + // 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; + 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, "../"); + FileName const build_support_dir = + get_build_support_dir(binary_dir, top_build_dir_location); + if (!fileSearch(build_support_dir.absFilename(), "Makefile").empty()) { + // Try and find "chkconfig.ltx". + string const system_support_dir = + addPath(Package::top_srcdir().absFilename(), "lib"); + + if (!fileSearch(system_support_dir, "chkconfig.ltx").empty()) { + lyxerr[Debug::INIT] << check_text << " yes" + << std::endl; + return std::make_pair(build_support_dir, system_support_dir); + } + } + + // Check whether binary is a symbolic link. + // If so, resolve it and repeat the exercise. + if (!fs::symbolic_link_exists(binary.toFilesystemEncoding())) + break; + + FileName link; + if (readLink(binary, link)) { + binary = link; + } else { + // Unable to resolve the link. + break; + } + } + + lyxerr[Debug::INIT] << check_text << " no" << std::endl; + return std::make_pair(FileName(), FileName()); +} + + +// Specification of document_dir_ may be reset by LyXRC, +// but the default is fixed for a given OS. +FileName const get_document_dir(FileName const & home_dir) +{ +#if defined (USE_WINDOWS_PACKAGING) + (void)home_dir; // Silence warning about unused variable. + os::GetFolderPath win32_folder_path; + return FileName(win32_folder_path(os::GetFolderPath::PERSONAL)); +#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. +FileName const get_locale_dir(FileName const & system_support_dir) +{ + // 1. Use the "LYX_LOCALEDIR" environment variable. + FileName const path_env = extract_env_var_dir("LYX_LOCALEDIR"); + if (!path_env.empty() && check_env_var_dir(path_env, "LYX_LOCALEDIR")) + return path_env; + + // 2. Search for system_support_dir / + // The is OS-dependent. (On Unix, it will + // be "../locale/".) + FileName path(normalizePath(addPath(system_support_dir.absFilename(), + relative_locale_dir()))); + + if (fs::exists(path.toFilesystemEncoding()) && + fs::is_directory(path.toFilesystemEncoding())) + return path; + + // 3. Fall back to the hard-coded LOCALEDIR. + path = hardcoded_localedir(); + if (fs::exists(path.toFilesystemEncoding()) && + fs::is_directory(path.toFilesystemEncoding())) + return path; + + return FileName(); +} + + +// 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); + return FileName(os::internal_path(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) +{ + if (command_line.empty()) + return FileName(); + + string const path = fix_dir_name(command_line); + return os::is_absolute_path(path) ? FileName(path) : makeAbsPath(path); +} + + +// Does the grunt work for abs_path_from_binary_name() +FileName const get_binary_path(string const & exe) +{ +#if defined (USE_WINDOWS_PACKAGING) + // 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"; +#else + string const exe_path = os::internal_path(exe); +#endif + if (os::is_absolute_path(exe_path)) + return FileName(exe_path); + + // Two possibilities present themselves. + // 1. The binary is relative to the CWD. + FileName const abs_exe_path = makeAbsPath(exe_path); + if (fs::exists(abs_exe_path.toFilesystemEncoding())) + return abs_exe_path; + + // 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); + if (exe_name != exe_path) + return FileName(); + + std::vector const path = getEnvPath("PATH"); + std::vector::const_iterator it = path.begin(); + std::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(); + + FileName const exe_path(addName(exe_dir, exe_name)); + if (fs::exists(exe_path.toFilesystemEncoding())) + return exe_path; + } + + // Didn't find anything. + return FileName(); +} + + +// Extracts the absolute path to the binary name received as argv[0]. +FileName const abs_path_from_binary_name(string const & exe) +{ + FileName const abs_binary = get_binary_path(exe); + if (abs_binary.empty()) { + // FIXME UNICODE + throw ExceptionMessage(ErrorException, + _("LyX binary not found"), + bformat(_("Unable to determine the path to the LyX binary from the command line %1$s"), + from_utf8(exe))); + } + return abs_binary; +} + + +// A plethora of directories is searched to ascertain the system +// lyxdir which is defined as the first directory to contain +// "chkconfig.ltx". +FileName const +get_system_support_dir(FileName const & abs_binary, + string const & command_line_system_support_dir) +{ + string const chkconfig_ltx = "chkconfig.ltx"; + + // searched_dirs is used for diagnostic purposes only in the case + // that "chkconfig.ltx" is not found. + std::list searched_dirs; + + // 1. Use the -sysdir command line parameter. + 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")) + return path; + } + + // 2. Use the "LYX_DIR_15x" environment variable. + path = extract_env_var_dir("LYX_DIR_15x"); + if (!path.empty()) { + searched_dirs.push_back(path); + if (check_env_var_dir(path, chkconfig_ltx, "LYX_DIR_15x")) + return path; + } + + // 3. Search relative to the lyx binary. + // We're looking for "chkconfig.ltx" in a directory + // OnlyPath(abs_binary) / / PACKAGE / + // PACKAGE is hardcoded in config.h. Eg "lyx" or "lyx-1.3.6cvs". + // is OS-dependent; on Unix, it will be "../share/". + string const relative_lyxdir = relative_system_support_dir(); + + // One subtlety to be aware of. 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; + while (true) { + // Try and find "chkconfig.ltx". + string const binary_dir = onlyPath(binary.absFilename()); + + FileName const lyxdir( + normalizePath(addPath(binary_dir, relative_lyxdir))); + searched_dirs.push_back(lyxdir); + + if (!fileSearch(lyxdir.absFilename(), chkconfig_ltx).empty()) { + // Success! "chkconfig.ltx" has been found. + return lyxdir; + } + + // Check whether binary is a symbolic link. + // If so, resolve it and repeat the exercise. + if (!fs::symbolic_link_exists(binary.toFilesystemEncoding())) + break; + + FileName link; + if (readLink(binary, link)) { + binary = link; + } else { + // Unable to resolve the link. + break; + } + } + + // 4. Repeat the exercise on the directory itself. + FileName binary_dir(onlyPath(abs_binary.absFilename())); + 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.toFilesystemEncoding())) + break; + + FileName link; + if (readLink(binary_dir, link)) { + binary_dir = link; + } else { + // Unable to resolve the link. + break; + } + + // Try and find "chkconfig.ltx". + FileName const lyxdir( + normalizePath(addPath(binary_dir.absFilename(), relative_lyxdir))); + searched_dirs.push_back(lyxdir); + + if (!fileSearch(lyxdir.absFilename(), chkconfig_ltx).empty()) { + // Success! "chkconfig.ltx" has been found. + return lyxdir; + } + } + + // 5. In desparation, try the hard-coded system support dir. + path = hardcoded_system_support_dir(); + if (!fileSearch(path.absFilename(), chkconfig_ltx).empty()) + return path; + + // Everything has failed :-( + // So inform the user and exit. + string searched_dirs_str; + typedef std::list::const_iterator iterator; + iterator const begin = searched_dirs.begin(); + iterator const end = searched_dirs.end(); + for (iterator it = begin; it != end; ++it) { + if (it != begin) + searched_dirs_str += "\n\t"; + 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(); +} + + +// Returns the absolute path to the user lyxdir, together with a flag +// indicating whether this directory was specified explicitly (as -userdir +// or through an environment variable) or whether it was deduced. +std::pair const +get_user_support_dir(FileName const & default_user_support_dir, + string const & command_line_user_support_dir) +{ + bool explicit_userdir = true; + + // 1. Use the -userdir command line parameter. + FileName path = + abs_path_from_command_line(command_line_user_support_dir); + if (!path.empty()) + return std::make_pair(path, explicit_userdir); + + // 2. Use the LYX_USERDIR_15x environment variable. + path = extract_env_var_dir("LYX_USERDIR_15x"); + if (!path.empty()) + return std::make_pair(path, explicit_userdir); + + // 3. Use the OS-dependent default_user_support_dir + explicit_userdir = false; + return std::make_pair(default_user_support_dir, explicit_userdir); +} + + +// $HOME/.lyx on POSIX but on Win32 it will be something like +// "C:/Documents and Settings/USERNAME/Application Data/LyX" +FileName const get_default_user_support_dir(FileName const & home_dir) +{ +#if defined (USE_WINDOWS_PACKAGING) + (void)home_dir; // Silence warning about unused variable. + + os::GetFolderPath win32_folder_path; + return FileName(addPath(win32_folder_path(os::GetFolderPath::APPDATA), PACKAGE)); + +#elif defined (USE_MACOSX_PACKAGING) + (void)home_dir; // Silence warning about unused variable. + + 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(); + + return FileName(addPath(reinterpret_cast(store), PACKAGE)); + +#else // USE_POSIX_PACKAGING + return FileName(addPath(home_dir.absFilename(), string(".") + PACKAGE)); +#endif +} + + +// Check that directory @c dir contains @c file. +// Else emit a warning about an invalid @c command_line_switch. +bool check_command_line_dir(string const & dir, + string const & file, + string const & command_line_switch) +{ + FileName const abs_path = fileSearch(dir, file); + if (abs_path.empty()) { + // FIXME UNICODE + throw ExceptionMessage(WarningException, _("File not found"), bformat( + _("Invalid %1$s switch.\nDirectory %2$s does not contain %3$s."), + from_utf8(command_line_switch), from_utf8(dir), + from_utf8(file))); + } + + return !abs_path.empty(); +} + + +// The environment variable @c env_var expands to a (single) file path. +FileName const extract_env_var_dir(string const & env_var) +{ + string const dir = fix_dir_name(getEnv(env_var)); + return dir.empty() ? FileName() : makeAbsPath(dir); +} + + +// Check that directory @c dir contains @c file. +// Else emit a warning about an invalid @c env_var. +bool check_env_var_dir(FileName const & dir, + string const & file, + string const & env_var) +{ + 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(file))); + } + + return !abs_path.empty(); +} + + +// Check that directory @c dir is indeed a directory. +// Else emit a warning about an invalid @c env_var. +bool check_env_var_dir(FileName const & dir, + string const & env_var) +{ + string const encoded(dir.toFilesystemEncoding()); + bool const success = (fs::exists(encoded) && fs::is_directory(encoded)); + + if (!success) { + // Put this string on a single line so that the gettext + // search mechanism in po/Makefile.in.in will register + // Package.cpp.in as a file containing strings that need + // translation. + // FIXME UNICODE + docstring const fmt = + _("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()))); + } + + return success; +} + + +// The locale directory relative to the LyX system directory. +string const relative_locale_dir() +{ +#if defined (USE_WINDOWS_PACKAGING) || defined (USE_MACOSX_PACKAGING) + return "locale/"; +#else + return "../locale/"; +#endif +} + + +// The system lyxdir is relative to the directory containing the LyX binary. +string const relative_system_support_dir() +{ + string result; + +#if defined (USE_WINDOWS_PACKAGING) || defined (USE_MACOSX_PACKAGING) + result = "../Resources/"; +#else // Posix-like. + result = addPath("../share/", PACKAGE); +#endif + + return result; +} + +} // namespace anon + +} // namespace support +} // namespace lyx diff --git a/src/support/Package.cpp.in b/src/support/Package.cpp.in deleted file mode 100644 index 0a6d8127d9..0000000000 --- a/src/support/Package.cpp.in +++ /dev/null @@ -1,751 +0,0 @@ -// -*- C++ -*- -/** - * \file package.C - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Angus Leeming - * - * Full author contact details are available in file CREDITS. - * - * Warning! This file is autogenerated from Package.cpp.in. - * All changes to this file will be lost. - */ - -#include - -#include "support/Package.h" - -#include "debug.h" -#include "gettext.h" - -#include "support/environment.h" -#include "support/filetools.h" -#include "support/lstrings.h" -#include "support/ExceptionMessage.h" -#include "support/os.h" - -#if defined (USE_WINDOWS_PACKAGING) -# include "support/os_win32.h" -#endif - -#include -#include - -#include -#include - -#if !defined (USE_WINDOWS_PACKAGING) && \ - !defined (USE_MACOSX_PACKAGING) && \ - !defined (USE_POSIX_PACKAGING) -#error USE_FOO_PACKAGING must be defined for FOO = WINDOWS, MACOSX or POSIX. -#endif - -#if defined (USE_MACOSX_PACKAGING) -# include // FSFindFolder, FSRefMakePath -#endif - -using std::string; - -namespace fs = boost::filesystem; - -namespace lyx { -namespace support { - -namespace { - -Package package_; -bool initialised_ = false; - -} // namespace anon - - -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) -{ - // 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); - 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... - // BOOST_ASSERT(initialised_); - return package_; -} - - -namespace { - -FileName const abs_path_from_binary_name(string const & exe); - -std::pair const -get_build_dirs(FileName const & abs_binary, - exe_build_dir_to_top_build_dir top_build_dir_location); - -FileName const get_document_dir(FileName const & home_dir); - -FileName const get_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); - -std::pair const -get_user_support_dir(FileName const & default_user_support_dir, - string const & command_line_user_support_dir); - - -string const & with_version_suffix(); - -} // 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) - : explicit_user_support_dir_(false) -{ - home_dir_ = get_home_dir(); - system_temp_dir_ = get_temp_dir(); - temp_dir_ = system_temp_dir_; - document_dir_ = get_document_dir(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); - - // Is LyX being run in-place from the build tree? - boost::tie(build_support_dir_, system_support_dir_) = - get_build_dirs(abs_binary, top_build_dir_location); - - if (build_support_dir_.empty()) - system_support_dir_ = - get_system_support_dir(abs_binary, - command_line_system_support_dir); - - locale_dir_ = get_locale_dir(system_support_dir_); - - FileName const default_user_support_dir = - get_default_user_support_dir(home_dir_); - boost::tie(user_support_dir_, explicit_user_support_dir_) = - get_user_support_dir(default_user_support_dir, - command_line_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' - << "\n" << std::endl; -} - - -namespace { - -// These next functions contain the stuff that is substituted at -// configuration-time. -FileName const hardcoded_localedir() -{ - // FIXME UNICODE - // The build system needs to make sure that this is in utf8 encoding. - return FileName("@LOCALEDIR@"); -} - - -FileName const hardcoded_system_support_dir() -{ - // FIXME UNICODE - // The build system needs to make sure that this is in utf8 encoding. - return FileName("@LYX_DIR@"); -} - - -string const & with_version_suffix() -{ - static string const program_suffix("@PROGRAM_SUFFIX@"); - static string const - with_version_suffix(" --with-version-suffix=@PROGRAM_SUFFIX@"); - return program_suffix.empty() ? program_suffix : with_version_suffix; -} - -} // namespace anon - - -FileName const & Package::top_srcdir() -{ - // FIXME UNICODE - // The build system needs to make sure that this is in utf8 encoding. - static FileName const dir("@TOP_SRCDIR@"); - return dir; -} - - -namespace { - -bool check_command_line_dir(string const & dir, - string const & file, - string const & command_line_switch); - -FileName const extract_env_var_dir(string const & env_var); - -bool check_env_var_dir(FileName const & dir, - string const & env_var); - -bool check_env_var_dir(FileName const & dir, - string const & file, - string const & env_var); - -string const relative_locale_dir(); - -string const relative_system_support_dir(); - - -/** - * Convert \p name to internal path and strip a trailing slash, since it - * comes from user input (commandline or environment). - * \p name is encoded in utf8. - */ -string const fix_dir_name(string const & name) -{ - return rtrim(os::internal_path(name), "/"); -} - - -FileName const -get_build_support_dir(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 FileName(normalizePath(addPath(binary_dir, indirection))); -} - - -std::pair const -get_build_dirs(FileName 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..."; - - // We're looking for "Makefile" in a directory - // binary_dir/../lib - // We're also looking for "chkconfig.ltx" in a directory - // top_srcdir()/lib - // If both are found, then we're running LyX in-place. - - // 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; - 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, "../"); - FileName const build_support_dir = - get_build_support_dir(binary_dir, top_build_dir_location); - if (!fileSearch(build_support_dir.absFilename(), "Makefile").empty()) { - // Try and find "chkconfig.ltx". - string const system_support_dir = - addPath(Package::top_srcdir().absFilename(), "lib"); - - if (!fileSearch(system_support_dir, "chkconfig.ltx").empty()) { - lyxerr[Debug::INIT] << check_text << " yes" - << std::endl; - return std::make_pair(build_support_dir, system_support_dir); - } - } - - // Check whether binary is a symbolic link. - // If so, resolve it and repeat the exercise. - if (!fs::symbolic_link_exists(binary.toFilesystemEncoding())) - break; - - FileName link; - if (readLink(binary, link)) { - binary = link; - } else { - // Unable to resolve the link. - break; - } - } - - lyxerr[Debug::INIT] << check_text << " no" << std::endl; - return std::make_pair(FileName(), FileName()); -} - - -// Specification of document_dir_ may be reset by LyXRC, -// but the default is fixed for a given OS. -FileName const get_document_dir(FileName const & home_dir) -{ -#if defined (USE_WINDOWS_PACKAGING) - (void)home_dir; // Silence warning about unused variable. - os::GetFolderPath win32_folder_path; - return FileName(win32_folder_path(os::GetFolderPath::PERSONAL)); -#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. -FileName const get_locale_dir(FileName const & system_support_dir) -{ - // 1. Use the "LYX_LOCALEDIR" environment variable. - FileName const path_env = extract_env_var_dir("LYX_LOCALEDIR"); - if (!path_env.empty() && check_env_var_dir(path_env, "LYX_LOCALEDIR")) - return path_env; - - // 2. Search for system_support_dir / - // The is OS-dependent. (On Unix, it will - // be "../locale/".) - FileName path(normalizePath(addPath(system_support_dir.absFilename(), - relative_locale_dir()))); - - if (fs::exists(path.toFilesystemEncoding()) && - fs::is_directory(path.toFilesystemEncoding())) - return path; - - // 3. Fall back to the hard-coded LOCALEDIR. - path = hardcoded_localedir(); - if (fs::exists(path.toFilesystemEncoding()) && - fs::is_directory(path.toFilesystemEncoding())) - return path; - - return FileName(); -} - - -// 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); - return FileName(os::internal_path(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) -{ - if (command_line.empty()) - return FileName(); - - string const path = fix_dir_name(command_line); - return os::is_absolute_path(path) ? FileName(path) : makeAbsPath(path); -} - - -// Does the grunt work for abs_path_from_binary_name() -FileName const get_binary_path(string const & exe) -{ -#if defined (USE_WINDOWS_PACKAGING) - // 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"; -#else - string const exe_path = os::internal_path(exe); -#endif - if (os::is_absolute_path(exe_path)) - return FileName(exe_path); - - // Two possibilities present themselves. - // 1. The binary is relative to the CWD. - FileName const abs_exe_path = makeAbsPath(exe_path); - if (fs::exists(abs_exe_path.toFilesystemEncoding())) - return abs_exe_path; - - // 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); - if (exe_name != exe_path) - return FileName(); - - std::vector const path = getEnvPath("PATH"); - std::vector::const_iterator it = path.begin(); - std::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(); - - FileName const exe_path(addName(exe_dir, exe_name)); - if (fs::exists(exe_path.toFilesystemEncoding())) - return exe_path; - } - - // Didn't find anything. - return FileName(); -} - - -// Extracts the absolute path to the binary name received as argv[0]. -FileName const abs_path_from_binary_name(string const & exe) -{ - FileName const abs_binary = get_binary_path(exe); - if (abs_binary.empty()) { - // FIXME UNICODE - throw ExceptionMessage(ErrorException, - _("LyX binary not found"), - bformat(_("Unable to determine the path to the LyX binary from the command line %1$s"), - from_utf8(exe))); - } - return abs_binary; -} - - -// A plethora of directories is searched to ascertain the system -// lyxdir which is defined as the first directory to contain -// "chkconfig.ltx". -FileName const -get_system_support_dir(FileName const & abs_binary, - string const & command_line_system_support_dir) -{ - string const chkconfig_ltx = "chkconfig.ltx"; - - // searched_dirs is used for diagnostic purposes only in the case - // that "chkconfig.ltx" is not found. - std::list searched_dirs; - - // 1. Use the -sysdir command line parameter. - 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")) - return path; - } - - // 2. Use the "LYX_DIR_15x" environment variable. - path = extract_env_var_dir("LYX_DIR_15x"); - if (!path.empty()) { - searched_dirs.push_back(path); - if (check_env_var_dir(path, chkconfig_ltx, "LYX_DIR_15x")) - return path; - } - - // 3. Search relative to the lyx binary. - // We're looking for "chkconfig.ltx" in a directory - // OnlyPath(abs_binary) / / PACKAGE / - // PACKAGE is hardcoded in config.h. Eg "lyx" or "lyx-1.3.6cvs". - // is OS-dependent; on Unix, it will be "../share/". - string const relative_lyxdir = relative_system_support_dir(); - - // One subtlety to be aware of. 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; - while (true) { - // Try and find "chkconfig.ltx". - string const binary_dir = onlyPath(binary.absFilename()); - - FileName const lyxdir( - normalizePath(addPath(binary_dir, relative_lyxdir))); - searched_dirs.push_back(lyxdir); - - if (!fileSearch(lyxdir.absFilename(), chkconfig_ltx).empty()) { - // Success! "chkconfig.ltx" has been found. - return lyxdir; - } - - // Check whether binary is a symbolic link. - // If so, resolve it and repeat the exercise. - if (!fs::symbolic_link_exists(binary.toFilesystemEncoding())) - break; - - FileName link; - if (readLink(binary, link)) { - binary = link; - } else { - // Unable to resolve the link. - break; - } - } - - // 4. Repeat the exercise on the directory itself. - FileName binary_dir(onlyPath(abs_binary.absFilename())); - 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.toFilesystemEncoding())) - break; - - FileName link; - if (readLink(binary_dir, link)) { - binary_dir = link; - } else { - // Unable to resolve the link. - break; - } - - // Try and find "chkconfig.ltx". - FileName const lyxdir( - normalizePath(addPath(binary_dir.absFilename(), relative_lyxdir))); - searched_dirs.push_back(lyxdir); - - if (!fileSearch(lyxdir.absFilename(), chkconfig_ltx).empty()) { - // Success! "chkconfig.ltx" has been found. - return lyxdir; - } - } - - // 5. In desparation, try the hard-coded system support dir. - path = hardcoded_system_support_dir(); - if (!fileSearch(path.absFilename(), chkconfig_ltx).empty()) - return path; - - // Everything has failed :-( - // So inform the user and exit. - string searched_dirs_str; - typedef std::list::const_iterator iterator; - iterator const begin = searched_dirs.begin(); - iterator const end = searched_dirs.end(); - for (iterator it = begin; it != end; ++it) { - if (it != begin) - searched_dirs_str += "\n\t"; - 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(); -} - - -// Returns the absolute path to the user lyxdir, together with a flag -// indicating whether this directory was specified explicitly (as -userdir -// or through an environment variable) or whether it was deduced. -std::pair const -get_user_support_dir(FileName const & default_user_support_dir, - string const & command_line_user_support_dir) -{ - bool explicit_userdir = true; - - // 1. Use the -userdir command line parameter. - FileName path = - abs_path_from_command_line(command_line_user_support_dir); - if (!path.empty()) - return std::make_pair(path, explicit_userdir); - - // 2. Use the LYX_USERDIR_15x environment variable. - path = extract_env_var_dir("LYX_USERDIR_15x"); - if (!path.empty()) - return std::make_pair(path, explicit_userdir); - - // 3. Use the OS-dependent default_user_support_dir - explicit_userdir = false; - return std::make_pair(default_user_support_dir, explicit_userdir); -} - - -// $HOME/.lyx on POSIX but on Win32 it will be something like -// "C:/Documents and Settings/USERNAME/Application Data/LyX" -FileName const get_default_user_support_dir(FileName const & home_dir) -{ -#if defined (USE_WINDOWS_PACKAGING) - (void)home_dir; // Silence warning about unused variable. - - os::GetFolderPath win32_folder_path; - return FileName(addPath(win32_folder_path(os::GetFolderPath::APPDATA), PACKAGE)); - -#elif defined (USE_MACOSX_PACKAGING) - (void)home_dir; // Silence warning about unused variable. - - 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(); - - return FileName(addPath(reinterpret_cast(store), PACKAGE)); - -#else // USE_POSIX_PACKAGING - return FileName(addPath(home_dir.absFilename(), string(".") + PACKAGE)); -#endif -} - - -// Check that directory @c dir contains @c file. -// Else emit a warning about an invalid @c command_line_switch. -bool check_command_line_dir(string const & dir, - string const & file, - string const & command_line_switch) -{ - FileName const abs_path = fileSearch(dir, file); - if (abs_path.empty()) { - // FIXME UNICODE - throw ExceptionMessage(WarningException, _("File not found"), bformat( - _("Invalid %1$s switch.\nDirectory %2$s does not contain %3$s."), - from_utf8(command_line_switch), from_utf8(dir), - from_utf8(file))); - } - - return !abs_path.empty(); -} - - -// The environment variable @c env_var expands to a (single) file path. -FileName const extract_env_var_dir(string const & env_var) -{ - string const dir = fix_dir_name(getEnv(env_var)); - return dir.empty() ? FileName() : makeAbsPath(dir); -} - - -// Check that directory @c dir contains @c file. -// Else emit a warning about an invalid @c env_var. -bool check_env_var_dir(FileName const & dir, - string const & file, - string const & env_var) -{ - 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(file))); - } - - return !abs_path.empty(); -} - - -// Check that directory @c dir is indeed a directory. -// Else emit a warning about an invalid @c env_var. -bool check_env_var_dir(FileName const & dir, - string const & env_var) -{ - string const encoded(dir.toFilesystemEncoding()); - bool const success = (fs::exists(encoded) && fs::is_directory(encoded)); - - if (!success) { - // Put this string on a single line so that the gettext - // search mechanism in po/Makefile.in.in will register - // Package.cpp.in as a file containing strings that need - // translation. - // FIXME UNICODE - docstring const fmt = - _("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()))); - } - - return success; -} - - -// The locale directory relative to the LyX system directory. -string const relative_locale_dir() -{ -#if defined (USE_WINDOWS_PACKAGING) || defined (USE_MACOSX_PACKAGING) - return "locale/"; -#else - return "../locale/"; -#endif -} - - -// The system lyxdir is relative to the directory containing the LyX binary. -string const relative_system_support_dir() -{ - string result; - -#if defined (USE_WINDOWS_PACKAGING) || defined (USE_MACOSX_PACKAGING) - result = "../Resources/"; -#else // Posix-like. - result = addPath("../share/", PACKAGE); -#endif - - return result; -} - -} // namespace anon - -} // namespace support -} // namespace lyx