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
[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])
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 \
development/MacOSX/spotlight/Makefile \
development/lyx.spec \
intl/Makefile \
- lib/Makefile \
+ lib/Makefile \
lib/doc/Makefile \
lib/lyx2lyx/lyx2lyx_version.py \
lib/lyx2lyx/Makefile \
#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
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})
${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)
LIBS += -L../lib
-LIBS += ../support/$(OBJECTS_DIR)/Package.o
LIBS += -Wl,--start-group
LIBS += -llyxmathed$${DEBUGSUFFIX}
LIBS += -llyxinsets$${DEBUGSUFFIX}
CPP += ForkedCallQueue.cpp
CPP += Forkedcall.cpp
CPP += ForkedcallsController.cpp
+CPP += Package.cpp
CPP += Path.cpp
CPP += Systemcall.cpp
CPP += Timeout.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} }
# 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
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
'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(),
ForkedCallQueue.cpp
Forkedcall.cpp
ForkedcallsController.cpp
+ Package.cpp
Path.cpp
Systemcall.cpp
Timeout.cpp
src_support_extra_src_files = Split('''
- Package.cpp.in
atexit.c
os_cygwin.cpp
os_unix.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
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
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
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
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 \
--- /dev/null
+// -*- 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 <config.h>
+
+#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 <boost/filesystem/operations.hpp>
+#include <boost/tuple/tuple.hpp>
+
+#include <list>
+#include <utility>
+
+#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 <CoreServices/CoreServices.h> // 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<FileName, FileName> 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<FileName, bool> 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]
+ << "<package>\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'
+ << "</package>\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<FileName, FileName> 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 / <relative locale dir>
+ // The <relative locale dir> 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<string> const path = getEnvPath("PATH");
+ std::vector<string>::const_iterator it = path.begin();
+ std::vector<string>::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<FileName> 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) / <relative dir> / PACKAGE /
+ // PACKAGE is hardcoded in config.h. Eg "lyx" or "lyx-1.3.6cvs".
+ // <relative dir> 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<FileName>::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<FileName, bool> 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<UInt8*>(store), PATH_MAX);
+ if (status_code != 0)
+ return FileName();
+
+ return FileName(addPath(reinterpret_cast<char const *>(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
+++ /dev/null
-// -*- 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 <config.h>
-
-#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 <boost/filesystem/operations.hpp>
-#include <boost/tuple/tuple.hpp>
-
-#include <list>
-#include <utility>
-
-#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 <CoreServices/CoreServices.h> // 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<FileName, FileName> 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<FileName, bool> 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]
- << "<package>\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'
- << "</package>\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<FileName, FileName> 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 / <relative locale dir>
- // The <relative locale dir> 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<string> const path = getEnvPath("PATH");
- std::vector<string>::const_iterator it = path.begin();
- std::vector<string>::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<FileName> 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) / <relative dir> / PACKAGE /
- // PACKAGE is hardcoded in config.h. Eg "lyx" or "lyx-1.3.6cvs".
- // <relative dir> 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<FileName>::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<FileName, bool> 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<UInt8*>(store), PATH_MAX);
- if (status_code != 0)
- return FileName();
-
- return FileName(addPath(reinterpret_cast<char const *>(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