From b3a983c66fe0b25c7fd86ebd4225976d8b3e6cb8 Mon Sep 17 00:00:00 2001 From: Enrico Forestieri Date: Fri, 13 May 2011 23:14:46 +0000 Subject: [PATCH] Backport the TEXINPUTS prefix feature. This should also fix bug #1751. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/branches/BRANCH_2_0_X@38746 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/Buffer.cpp | 13 ++++--- src/Converter.cpp | 16 +++++--- src/Format.cpp | 8 ++-- src/LaTeX.cpp | 12 +++--- src/LaTeX.h | 6 ++- src/LyXRC.cpp | 28 +++++++++++++- src/LyXRC.h | 6 +++ src/VCBackend.cpp | 2 +- src/frontends/qt4/GuiPrefs.cpp | 5 +++ src/frontends/qt4/ui/PrefPathsUi.ui | 25 ++++++++++++- src/support/Systemcall.cpp | 45 ++++++++++++++++++++--- src/support/Systemcall.h | 9 +++-- src/support/SystemcallPrivate.h | 2 +- src/support/filetools.cpp | 36 ++++++++++++++++++ src/support/filetools.h | 6 +++ src/support/os.h | 22 ++++++++--- src/support/os_cygwin.cpp | 47 +++++++++++++++++++++--- src/support/os_unix.cpp | 26 ++++++++++++- src/support/os_win32.cpp | 57 +++++++++++++++++++++++++++-- status.20x | 5 +++ 20 files changed, 327 insertions(+), 49 deletions(-) diff --git a/src/Buffer.cpp b/src/Buffer.cpp index f51084e8ef..47c82ccb7e 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -2028,7 +2028,7 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) // Execute the command in the background Systemcall call; - call.startscript(Systemcall::DontWait, command); + call.startscript(Systemcall::DontWait, command, filePath()); break; } @@ -2206,7 +2206,8 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) command2 += quoteName(psname); // First run dvips. // If successful, then spool command - res = one.startscript(Systemcall::Wait, command); + res = one.startscript(Systemcall::Wait, command, + filePath()); if (res == 0) { // If there's no GUI, we have to wait on this command. Otherwise, @@ -2214,7 +2215,8 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) // file, before it can be printed!! Systemcall::Starttype stype = use_gui ? Systemcall::DontWait : Systemcall::Wait; - res = one.startscript(stype, command2); + res = one.startscript(stype, command2, + filePath()); } } else { // case 2: print directly to a printer @@ -2223,7 +2225,8 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) // as above.... Systemcall::Starttype stype = use_gui ? Systemcall::DontWait : Systemcall::Wait; - res = one.startscript(stype, command + quoteName(dviname)); + res = one.startscript(stype, command + + quoteName(dviname), filePath()); } } else { @@ -2246,7 +2249,7 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) // as above.... Systemcall::Starttype stype = use_gui ? Systemcall::DontWait : Systemcall::Wait; - res = one.startscript(stype, command); + res = one.startscript(stype, command, filePath()); } if (res == 0) diff --git a/src/Converter.cpp b/src/Converter.cpp index 087b0b6af3..ff1d7093bf 100644 --- a/src/Converter.cpp +++ b/src/Converter.cpp @@ -307,7 +307,8 @@ bool Converters::convert(Buffer const * buffer, LYXERR(Debug::FILES, "No converter defined! " "I use convertDefault.py:\n\t" << command); Systemcall one; - one.startscript(Systemcall::Wait, command); + one.startscript(Systemcall::Wait, command, buffer ? + buffer->filePath() : string()); if (to_file.isReadableFile()) { if (conversionflags & try_cache) ConverterCache::get().add(orig_from, @@ -443,12 +444,15 @@ bool Converters::convert(Buffer const * buffer, int res; if (dummy) { res = one.startscript(Systemcall::DontWait, - to_filesystem8bit(from_utf8(command))); + to_filesystem8bit(from_utf8(command)), + buffer ? buffer->filePath() : string()); // We're not waiting for the result, so we can't do anything // else here. } else { res = one.startscript(Systemcall::Wait, - to_filesystem8bit(from_utf8(command))); + to_filesystem8bit(from_utf8(command)), + buffer ? buffer->filePath() + : string()); if (!real_outfile.empty()) { Mover const & mover = getMover(conv.to); if (!mover.rename(outfile, real_outfile)) @@ -468,7 +472,8 @@ bool Converters::convert(Buffer const * buffer, " < " + quoteName(infile2 + ".out") + " > " + quoteName(logfile); one.startscript(Systemcall::Wait, - to_filesystem8bit(from_utf8(command2))); + to_filesystem8bit(from_utf8(command2)), + buffer->filePath()); if (!scanLog(*buffer, command, makeAbsPath(logfile, path), errorList)) return false; } @@ -612,7 +617,8 @@ bool Converters::runLaTeX(Buffer const & buffer, string const & command, // do the LaTeX run(s) string const name = buffer.latexName(); - LaTeX latex(command, runparams, FileName(makeAbsPath(name))); + LaTeX latex(command, runparams, FileName(makeAbsPath(name)), + buffer.filePath()); TeXErrors terr; ShowMessage show(buffer); latex.message.connect(show); diff --git a/src/Format.cpp b/src/Format.cpp index ec61b84387..cc85b85000 100644 --- a/src/Format.cpp +++ b/src/Format.cpp @@ -285,7 +285,7 @@ bool Formats::view(Buffer const & buffer, FileName const & filename, } // viewer is 'auto' if (format->viewer() == "auto") { - if (os::autoOpenFile(filename.absFileName(), os::VIEW)) + if (os::autoOpenFile(filename.absFileName(), os::VIEW, buffer.filePath())) return true; else { Alert::error(_("Cannot view file"), @@ -320,7 +320,7 @@ bool Formats::view(Buffer const & buffer, FileName const & filename, buffer.message(_("Executing command: ") + from_utf8(command)); Systemcall one; - one.startscript(Systemcall::DontWait, command); + one.startscript(Systemcall::DontWait, command, buffer.filePath()); // we can't report any sort of error, since we aren't waiting return true; @@ -364,7 +364,7 @@ bool Formats::edit(Buffer const & buffer, FileName const & filename, // editor is 'auto' if (format->editor() == "auto") { - if (os::autoOpenFile(filename.absFileName(), os::EDIT)) + if (os::autoOpenFile(filename.absFileName(), os::EDIT, buffer.filePath())) return true; else { Alert::error(_("Cannot edit file"), @@ -387,7 +387,7 @@ bool Formats::edit(Buffer const & buffer, FileName const & filename, buffer.message(_("Executing command: ") + from_utf8(command)); Systemcall one; - one.startscript(Systemcall::DontWait, command); + one.startscript(Systemcall::DontWait, command, buffer.filePath()); // we can't report any sort of error, since we aren't waiting return true; diff --git a/src/LaTeX.cpp b/src/LaTeX.cpp index 1596ba1e82..f1d7b1a779 100644 --- a/src/LaTeX.cpp +++ b/src/LaTeX.cpp @@ -93,8 +93,8 @@ bool operator!=(AuxInfo const & a, AuxInfo const & o) */ LaTeX::LaTeX(string const & latex, OutputParams const & rp, - FileName const & f) - : cmd(latex), file(f), runparams(rp) + FileName const & f, string const & p) + : cmd(latex), file(f), path(p), runparams(rp) { num_errors = 0; if (prefixIs(cmd, "pdf")) { // Do we use pdflatex ? @@ -421,7 +421,7 @@ int LaTeX::startscript() + quoteName(onlyFileName(file.toFilesystemEncoding())) + " > " + os::nulldev(); Systemcall one; - return one.startscript(Systemcall::Wait, tmp); + return one.startscript(Systemcall::Wait, tmp, path); } @@ -448,7 +448,7 @@ bool LaTeX::runMakeIndex(string const & f, OutputParams const & runparams, tmp += quoteName(f); tmp += params; Systemcall one; - one.startscript(Systemcall::Wait, tmp); + one.startscript(Systemcall::Wait, tmp, path); return true; } @@ -464,7 +464,7 @@ bool LaTeX::runMakeIndexNomencl(FileName const & file, tmp += " -o " + onlyFileName(changeExtension(file.toFilesystemEncoding(), nls)); Systemcall one; - one.startscript(Systemcall::Wait, tmp); + one.startscript(Systemcall::Wait, tmp, path); return true; } @@ -604,7 +604,7 @@ bool LaTeX::runBibTeX(vector const & bibtex_info, tmp += quoteName(onlyFileName(removeExtension( it->aux_file.absFileName()))); Systemcall one; - one.startscript(Systemcall::Wait, tmp); + one.startscript(Systemcall::Wait, tmp, path); } // Return whether bibtex was run return result; diff --git a/src/LaTeX.h b/src/LaTeX.h index 85088209ca..4d1c3356d8 100644 --- a/src/LaTeX.h +++ b/src/LaTeX.h @@ -151,7 +151,8 @@ public: path = name of the files original path. */ LaTeX(std::string const & cmd, OutputParams const &, - support::FileName const & file); + support::FileName const & file, + std::string const & path = empty_string()); /// runs LaTeX several times int run(TeXErrors &); @@ -210,6 +211,9 @@ private: /// support::FileName file; + /// + std::string path; + /// used by scanLogFile int num_errors; diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp index 20daf4ac20..983eca3af5 100644 --- a/src/LyXRC.cpp +++ b/src/LyXRC.cpp @@ -192,6 +192,7 @@ LexerKeyword lyxrcTags[] = { { "\\template_path", LyXRC::RC_TEMPLATEPATH }, { "\\tex_allows_spaces", LyXRC::RC_TEX_ALLOWS_SPACES }, { "\\tex_expects_windows_paths", LyXRC::RC_TEX_EXPECTS_WINDOWS_PATHS }, + { "\\texinputs_prefix", LyXRC::RC_TEXINPUTS_PREFIX }, { "\\thesaurusdir_path", LyXRC::RC_THESAURUSDIRPATH }, { "\\ui_file", LyXRC::RC_UIFILE }, { "\\use_converter_cache", LyXRC::RC_USE_CONVERTER_CACHE }, @@ -227,6 +228,8 @@ void LyXRC::setDefaults() bind_file = "cua"; def_file = "default"; ui_file = "default"; + // The current document directory + texinputs_prefix = "."; // Get printer from the environment. If fail, use default "", // assuming that everything is set up correctly. printer = getEnv("PRINTER"); @@ -499,6 +502,10 @@ LyXRC::ReturnValues LyXRC::read(Lexer & lexrc, bool check_format) lexrc >> tex_allows_spaces; break; + case RC_TEXINPUTS_PREFIX: + lexrc >> texinputs_prefix; + break; + case RC_KBMAP: lexrc >> use_kbmap; break; @@ -2213,6 +2220,14 @@ void LyXRC::write(ostream & os, bool ignore_system_lyxrc, string const & name) c << "# TEX SECTION #######################################\n" << "#\n\n"; + case RC_TEXINPUTS_PREFIX: + if (ignore_system_lyxrc || + texinputs_prefix != system_lyxrc.texinputs_prefix) { + os << "\\texinputs_prefix \"" << texinputs_prefix << "\"\n"; + } + if (tag != RC_LAST) + break; + case RC_FONT_ENCODING: if (ignore_system_lyxrc || fontenc != system_lyxrc.fontenc) { @@ -3020,6 +3035,10 @@ void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new) if (lyxrc_orig.windows_style_tex_paths != lyxrc_new.windows_style_tex_paths) { os::windows_style_tex_paths(lyxrc_new.windows_style_tex_paths); } + case LyXRC::RC_TEXINPUTS_PREFIX: + if (lyxrc_orig.texinputs_prefix != lyxrc_new.texinputs_prefix) { + lyxrc.texinputs_prefix = lyxrc_new.texinputs_prefix; + } case LyXRC::RC_THESAURUSDIRPATH: case LyXRC::RC_UIFILE: case LyXRC::RC_USER_EMAIL: @@ -3313,7 +3332,7 @@ string const LyXRC::getDescription(LyXRCTags tag) case RC_PATH_PREFIX: str = _("Specify those directories which should be " - "prepended to the PATH environment variable. " + "prepended to the PATH environment variable.\n" "Use the OS native format."); break; @@ -3470,6 +3489,13 @@ string const LyXRC::getDescription(LyXRCTags tag) case RC_TEX_EXPECTS_WINDOWS_PATHS: break; + case RC_TEXINPUTS_PREFIX: + str = _("Specify those directories which should be " + "prepended to the TEXINPUTS environment variable.\n" + "A '.' represents the current document directory. " + "Use the OS native format."); + break; + case RC_UIFILE: str = _("The UI (user interface) file. Can either specify an absolute path, or LyX will look in its global and local ui/ directories."); break; diff --git a/src/LyXRC.h b/src/LyXRC.h index e8e4ee16db..9b067da329 100644 --- a/src/LyXRC.h +++ b/src/LyXRC.h @@ -174,6 +174,7 @@ public: RC_TEMPLATEPATH, RC_TEX_ALLOWS_SPACES, RC_TEX_EXPECTS_WINDOWS_PATHS, + RC_TEXINPUTS_PREFIX, RC_THESAURUSDIRPATH, RC_UIFILE, RC_USELASTFILEPOS, @@ -469,6 +470,11 @@ public: * The string is input, stored and output in native format. */ std::string path_prefix; + /** Prepend paths to the TEXINPUTS environment variable. + * The string is input, stored and output in native format. + * A '.' here stands for the current document directory. + */ + std::string texinputs_prefix; /// Use the cache for file converters? bool use_converter_cache; /// The maximum age of cache files in seconds diff --git a/src/VCBackend.cpp b/src/VCBackend.cpp index bc47719480..342584284a 100644 --- a/src/VCBackend.cpp +++ b/src/VCBackend.cpp @@ -43,7 +43,7 @@ int VCS::doVCCommandCall(string const & cmd, FileName const & path) LYXERR(Debug::LYXVC, "doVCCommandCall: " << cmd); Systemcall one; support::PathChanger p(path); - return one.startscript(Systemcall::Wait, cmd, false); + return one.startscript(Systemcall::Wait, cmd, string(), false); } diff --git a/src/frontends/qt4/GuiPrefs.cpp b/src/frontends/qt4/GuiPrefs.cpp index dfac183249..24b9a47f68 100644 --- a/src/frontends/qt4/GuiPrefs.cpp +++ b/src/frontends/qt4/GuiPrefs.cpp @@ -1312,6 +1312,9 @@ PrefPaths::PrefPaths(GuiPreferences * form) connect(pathPrefixED, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); + + connect(texinputsPrefixED, SIGNAL(textChanged(QString)), + this, SIGNAL(changed())); } @@ -1325,6 +1328,7 @@ void PrefPaths::apply(LyXRC & rc) const rc.thesaurusdir_path = internal_path(fromqstr(thesaurusDirED->text())); rc.hunspelldir_path = internal_path(fromqstr(hunspellDirED->text())); rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text())); + rc.texinputs_prefix = internal_path_list(fromqstr(texinputsPrefixED->text())); // FIXME: should be a checkbox only rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text())); } @@ -1340,6 +1344,7 @@ void PrefPaths::update(LyXRC const & rc) thesaurusDirED->setText(toqstr(external_path(rc.thesaurusdir_path))); hunspellDirED->setText(toqstr(external_path(rc.hunspelldir_path))); pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix))); + texinputsPrefixED->setText(toqstr(external_path_list(rc.texinputs_prefix))); // FIXME: should be a checkbox only lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes))); } diff --git a/src/frontends/qt4/ui/PrefPathsUi.ui b/src/frontends/qt4/ui/PrefPathsUi.ui index cab4cba8c0..b1792c5328 100644 --- a/src/frontends/qt4/ui/PrefPathsUi.ui +++ b/src/frontends/qt4/ui/PrefPathsUi.ui @@ -19,7 +19,7 @@ 6 - + Qt::Vertical @@ -46,7 +46,28 @@ - + + + Specify those directories which should be prepended to the PATH environment variable. Use the OS native format. + + + + + + + TEX&INPUTS prefix: + + + texinputsPrefixED + + + + + + + Specify those directories which should be prepended to the TEXINPUTS environment variable. A '.' represents the current document directory. Use the OS native format. + + diff --git a/src/support/Systemcall.cpp b/src/support/Systemcall.cpp index 8cedb09a33..0753c590c8 100644 --- a/src/support/Systemcall.cpp +++ b/src/support/Systemcall.cpp @@ -14,6 +14,8 @@ #include #include "support/debug.h" +#include "support/environment.h" +#include "support/filetools.h" #include "support/lstrings.h" #include "support/qstring_helpers.h" #include "support/Systemcall.h" @@ -21,6 +23,7 @@ #include "support/os.h" #include "support/ProgressInterface.h" +#include "LyXRC.h" #include #include @@ -96,9 +99,26 @@ ProgressInterface* ProgressInterface::instance() // Reuse of instance #ifndef USE_QPROCESS int Systemcall::startscript(Starttype how, string const & what, - bool /*process_events*/) + std::string const & path, bool /*process_events*/) { - string command = what; + string command; + string const texinputs = os::latex_path_list( + replaceCurdirPath(path, lyxrc.texinputs_prefix)); + string const sep = string(1, os::path_separator(os::TEXENGINE)); + string const env = getEnv("TEXINPUTS"); + + switch (os::shell()) { + case os::UNIX: + command = path.empty() || lyxrc.texinputs_prefix.empty() ? what + : "env TEXINPUTS='." + sep + texinputs + + sep + env + "' " + what; + break; + case os::CMD_EXE: + command = path.empty() || lyxrc.texinputs_prefix.empty() ? what + : "set TEXINPUTS=." + sep + texinputs + + sep + env + " & " + what; + break; + } if (how == DontWait) { switch (os::shell()) { @@ -204,7 +224,8 @@ string const parsecmd(string const & inputcmd, string & outfile) -int Systemcall::startscript(Starttype how, string const & what, bool process_events) +int Systemcall::startscript(Starttype how, string const & what, + string const & path, bool process_events) { string outfile; QString cmd = toqstr(parsecmd(what, outfile)); @@ -212,7 +233,7 @@ int Systemcall::startscript(Starttype how, string const & what, bool process_eve SystemcallPrivate d(outfile); - d.startProcess(cmd); + d.startProcess(cmd, path); if (!d.waitWhile(SystemcallPrivate::Starting, process_events, -1)) { LYXERR0("Systemcall: '" << cmd << "' did not start!"); LYXERR0("error " << d.errorMessage()); @@ -264,10 +285,24 @@ SystemcallPrivate::SystemcallPrivate(const std::string& of) : -void SystemcallPrivate::startProcess(const QString& cmd) +void SystemcallPrivate::startProcess(QString const & cmd, string const & path) { cmd_ = cmd; if (process_) { + if (!path.empty() && !lyxrc.texinputs_prefix.empty()) { + QString const texinputs = toqstr(os::latex_path_list( + replaceCurdirPath(path, lyxrc.texinputs_prefix))); + QChar const sep = os::path_separator(os::TEXENGINE); + QString const prefix = QLatin1String("TEXINPUTS=.") + + sep + texinputs + sep; + QStringList env = QProcess::systemEnvironment(); + if (env.filter("TEXINPUTS=").isEmpty()) + env << prefix; + else + env.replaceInStrings(QRegExp("^TEXINPUTS=(.*)"), + prefix + "\\1"); + process_->setEnvironment(env); + } state = SystemcallPrivate::Starting; process_->start(cmd_); } diff --git a/src/support/Systemcall.h b/src/support/Systemcall.h index 6d7d708e05..71e4c6237d 100644 --- a/src/support/Systemcall.h +++ b/src/support/Systemcall.h @@ -40,10 +40,13 @@ public: /** Start child process. * The string "what" contains a commandline with arguments separated - * by spaces. Unset "process_events" in case UI should be blocked while - * processing the external command. + * by spaces. The string "path" contains the path to be prepended to + * the TEXINPUTS environment variable. Unset "process_events" in + * case UI should be blocked while processing the external command. */ - int startscript(Starttype how, std::string const & what, bool process_events = false); + int startscript(Starttype how, std::string const & what, + std::string const & path = empty_string(), + bool process_events = false); }; } // namespace support diff --git a/src/support/SystemcallPrivate.h b/src/support/SystemcallPrivate.h index c8e3aa734c..c0a4c7755a 100644 --- a/src/support/SystemcallPrivate.h +++ b/src/support/SystemcallPrivate.h @@ -44,7 +44,7 @@ public: State state; bool waitWhile(State, bool processEvents, int timeout = -1); - void startProcess(const QString& cmd); + void startProcess(QString const & cmd, std::string const & path); int exitCode(); diff --git a/src/support/filetools.cpp b/src/support/filetools.cpp index 10387de422..dbf91ee59e 100644 --- a/src/support/filetools.cpp +++ b/src/support/filetools.cpp @@ -577,6 +577,42 @@ string const replaceEnvironmentPath(string const & path) } +// Replace current directory in all elements of a path list with a given path. +string const replaceCurdirPath(string const & path, string const & pathlist) +{ + string const oldpathlist = replaceEnvironmentPath(pathlist); + char const sep = os::path_separator(); + string newpathlist; + + for (size_t i = 0, k = 0; i != string::npos; k = i) { + i = oldpathlist.find(sep, i); + string p = oldpathlist.substr(k, i - k); + if (FileName::isAbsolute(p)) { + newpathlist += p; + } else if (i > k) { + size_t offset = 0; + if (p == ".") { + offset = 1; + } else if (prefixIs(p, "./")) { + offset = 2; + while (p[offset] == '/') + ++offset; + } + newpathlist += addPath(path, p.substr(offset)); + if (suffixIs(p, "//")) + newpathlist += '/'; + } + if (i != string::npos) { + newpathlist += sep; + // Stop here if the last element is empty + if (++i == oldpathlist.length()) + break; + } + } + return newpathlist; +} + + // Make relative path out of two absolute paths docstring const makeRelPath(docstring const & abspath, docstring const & basepath) // Makes relative path out of absolute path. If it is deeper than basepath, diff --git a/src/support/filetools.h b/src/support/filetools.h index cd25d47200..001c0f3ddc 100644 --- a/src/support/filetools.h +++ b/src/support/filetools.h @@ -247,6 +247,12 @@ std::string const onlyFileName(std::string const & fname); */ std::string const replaceEnvironmentPath(std::string const & path); +/** Replace all references to a current directory (a lonely '.' or + the prefix "./") in \c pathlist with \c path. Also prefixes + all non-absolute paths with \c path. +*/ +std::string const replaceCurdirPath(std::string const & path, std::string const & pathlist); + /** Set \c link to the path \c file points to as a symbolic link. \return true if successful. */ diff --git a/src/support/os.h b/src/support/os.h index 8d1744bf7e..d66173b1a7 100644 --- a/src/support/os.h +++ b/src/support/os.h @@ -104,6 +104,12 @@ std::string internal_path_list(std::string const & p); */ std::string latex_path(std::string const & p); +/** + * Converts a platform style path list into a form suitable for the TeX engine. + * \p p is encoded in utf8. + */ +std::string latex_path_list(std::string const & p); + /// Checks if the format string is suitable on the OS bool is_valid_strftime(std::string const & p); @@ -112,10 +118,15 @@ bool is_valid_strftime(std::string const & p); */ char const * popen_read_mode(); -/** The character used to separate paths returned by the - * PATH environment variable. +enum path_type { + PLATFORM, + TEXENGINE +}; + +/** The character used to separate paths for platform environment variables + * (such as PATH) or for the TeX engine. */ -char path_separator(); +char path_separator(path_type type = PLATFORM); /** If @c use_windows_paths is true, LyX will output Windows-style paths to * latex files rather than posix ones. Obviously, this option is used only @@ -133,14 +144,15 @@ enum auto_open_mode { * \param mode can be opened in VIEW or EDIT mode * \returns whether or not the format can be opened according to \p mode */ -bool canAutoOpenFile(std::string const & ext, auto_open_mode const mode = VIEW); +bool canAutoOpenFile(std::string const & ext, auto_open_mode const mode); /** View or edit a file with the default viewer or editor. * \param filename file to open (encoded in utf8) * \param mode open in VIEW or EDIT mode * \returns whether or not the file is viewed (or edited) successfully. */ -bool autoOpenFile(std::string const & filename, auto_open_mode const mode = VIEW); +bool autoOpenFile(std::string const & filename, auto_open_mode const mode, + std::string const & path = empty_string()); /** Resolves a path such that it does not contain '.', '..', or symbolic links. * \p path and the return value are encoded in utf8. diff --git a/src/support/os_cygwin.cpp b/src/support/os_cygwin.cpp index 6f5d57fdaf..389b4e2f78 100644 --- a/src/support/os_cygwin.cpp +++ b/src/support/os_cygwin.cpp @@ -15,12 +15,16 @@ #include +#include "LyXRC.h" + #include "support/os.h" +#include "support/debug.h" +#include "support/environment.h" #include "support/FileName.h" +#include "support/filetools.h" #include "support/lassert.h" #include "support/lstrings.h" -#include "support/debug.h" #include #include @@ -343,6 +347,19 @@ string latex_path(string const & p) } +string latex_path_list(string const & p) +{ + // We may need a posix style path or a windows style path (depending + // on windows_style_tex_paths_), but we use always forward slashes, + // since this is standard for all tex engines. + + if (windows_style_tex_paths_) + return convert_path_list(p, PathStyle(windows)); + + return convert_path_list(p, PathStyle(posix)); +} + + bool is_valid_strftime(string const & p) { string::size_type pos = p.find_first_of('%'); @@ -387,8 +404,11 @@ int timeout_min() } -char path_separator() +char path_separator(path_type type) { + if (type == TEXENGINE) + return windows_style_tex_paths_ ? ';' : ':'; + return ':'; } @@ -415,13 +435,30 @@ bool canAutoOpenFile(string const & ext, auto_open_mode const mode) } -bool autoOpenFile(string const & filename, auto_open_mode const mode) +bool autoOpenFile(string const & filename, auto_open_mode const mode, + string const & path) { + string const texinputs = os::latex_path_list( + replaceCurdirPath(path, lyxrc.texinputs_prefix)); + string const sep = windows_style_tex_paths_ ? ";" : ":"; + string const oldval = getEnv("TEXINPUTS"); + string const newval = "." + sep + texinputs + sep + oldval; + if (!path.empty() && !lyxrc.texinputs_prefix.empty()) { + setEnv("TEXINPUTS", newval); + cygwin_internal(CW_SYNC_WINENV); + } + // reference: http://msdn.microsoft.com/en-us/library/bb762153.aspx string const win_path = to_local8bit(from_utf8(convert_path(filename, PathStyle(windows)))); char const * action = (mode == VIEW) ? "open" : "edit"; - return reinterpret_cast(ShellExecute(NULL, action, - win_path.c_str(), NULL, NULL, 1)) > 32; + bool success = reinterpret_cast(ShellExecute(NULL, action, + win_path.c_str(), NULL, NULL, 1)) > 32; + + if (!path.empty() && !lyxrc.texinputs_prefix.empty()) { + setEnv("TEXINPUTS", oldval); + cygwin_internal(CW_SYNC_WINENV); + } + return success; } diff --git a/src/support/os_unix.cpp b/src/support/os_unix.cpp index 8727cff2b7..b8a94b2c56 100644 --- a/src/support/os_unix.cpp +++ b/src/support/os_unix.cpp @@ -12,9 +12,13 @@ #include +#include "LyXRC.h" + #include "support/os.h" #include "support/docstring.h" +#include "support/environment.h" #include "support/FileName.h" +#include "support/filetools.h" #include "support/lstrings.h" #include "support/lassert.h" @@ -176,6 +180,12 @@ string latex_path(string const & p) } +string latex_path_list(string const & p) +{ + return p; +} + + bool is_valid_strftime(string const & p) { string::size_type pos = p.find_first_of('%'); @@ -218,7 +228,7 @@ int timeout_min() } -char path_separator() +char path_separator(path_type) { return ':'; } @@ -258,7 +268,8 @@ bool canAutoOpenFile(string const & ext, auto_open_mode const mode) } -bool autoOpenFile(string const & filename, auto_open_mode const mode) +bool autoOpenFile(string const & filename, auto_open_mode const mode, + string const & path) { #ifdef __APPLE__ // Reference: http://developer.apple.com/documentation/Carbon/Reference/LaunchServicesReference/ @@ -279,6 +290,13 @@ bool autoOpenFile(string const & filename, auto_open_mode const mode) if (status == kLSApplicationNotFoundErr) return false; + string const texinputs = os::latex_path_list( + replaceCurdirPath(path, lyxrc.texinputs_prefix)); + string const oldval = getEnv("TEXINPUTS"); + string const newval = ".:" + texinputs + ":" + oldval; + if (!path.empty() && !lyxrc.texinputs_prefix.empty()) + setEnv("TEXINPUTS", newval); + LSLaunchFSRefSpec inLaunchSpec; inLaunchSpec.appRef = &outAppRef; inLaunchSpec.numDocs = 1; @@ -288,11 +306,15 @@ bool autoOpenFile(string const & filename, auto_open_mode const mode) inLaunchSpec.asyncRefCon = NULL; status = LSOpenFromRefSpec(&inLaunchSpec, NULL); + if (!path.empty() && !lyxrc.texinputs_prefix.empty()) + setEnv("TEXINPUTS", oldval); + return status != kLSApplicationNotFoundErr; #else // silence compiler warnings (void)filename; (void)mode; + (void)path; // currently, no default viewer is tried for non-windows system // support for KDE/Gnome/Macintosh may be added later diff --git a/src/support/os_win32.cpp b/src/support/os_win32.cpp index 2caf085691..72bf218a04 100644 --- a/src/support/os_win32.cpp +++ b/src/support/os_win32.cpp @@ -15,10 +15,13 @@ #include +#include "LyXRC.h" + #include "support/os.h" #include "support/os_win32.h" #include "support/debug.h" +#include "support/environment.h" #include "support/FileName.h" #include "support/gettext.h" #include "support/filetools.h" @@ -385,6 +388,38 @@ string latex_path(string const & p) } +string latex_path_list(string const & p) +{ + if (p.empty()) + return p; + + // We may need a posix style path or a windows style path (depending + // on windows_style_tex_paths_), but we use always forward slashes, + // since this is standard for all tex engines. + + if (!windows_style_tex_paths_) { + string pathlist; + for (size_t i = 0, k = 0; i != string::npos; k = i) { + i = p.find(';', i); + string path = subst(p.substr(k, i - k), '\\', '/'); + if (FileName::isAbsolute(path)) { + string const drive = path.substr(0, 2); + string const cygprefix = cygdrive + "/" + + drive.substr(0, 1); + path = subst(path, drive, cygprefix); + } + pathlist += path; + if (i != string::npos) { + pathlist += ':'; + ++i; + } + } + return pathlist; + } + return subst(p, '\\', '/'); +} + + bool is_valid_strftime(string const & p) { string::size_type pos = p.find_first_of('%'); @@ -429,8 +464,11 @@ int timeout_min() } -char path_separator() +char path_separator(path_type type) { + if (type == TEXENGINE) + return windows_style_tex_paths_ ? ';' : ':'; + return ';'; } @@ -507,12 +545,25 @@ bool canAutoOpenFile(string const & ext, auto_open_mode const mode) } -bool autoOpenFile(string const & filename, auto_open_mode const mode) +bool autoOpenFile(string const & filename, auto_open_mode const mode, + string const & path) { + string const texinputs = os::latex_path_list( + replaceCurdirPath(path, lyxrc.texinputs_prefix)); + string const sep = windows_style_tex_paths_ ? ";" : ":"; + string const oldval = getEnv("TEXINPUTS"); + string const newval = "." + sep + texinputs + sep + oldval; + if (!path.empty() && !lyxrc.texinputs_prefix.empty()) + setEnv("TEXINPUTS", newval); + // reference: http://msdn.microsoft.com/en-us/library/bb762153.aspx char const * action = (mode == VIEW) ? "open" : "edit"; - return reinterpret_cast(ShellExecute(NULL, action, + bool success = reinterpret_cast(ShellExecute(NULL, action, to_local8bit(from_utf8(filename)).c_str(), NULL, NULL, 1)) > 32; + + if (!path.empty() && !lyxrc.texinputs_prefix.empty()) + setEnv("TEXINPUTS", oldval); + return success; } diff --git a/status.20x b/status.20x index b7ab425491..d50f923160 100644 --- a/status.20x +++ b/status.20x @@ -30,6 +30,11 @@ What's new - Improved XHTML output of various fractions. +- A prefix for the TEXINPUTS environment variable can be specified in the + preferences. The directory of a LyX document is represented by a single + dot '.' or by the prefix "./". Also, any non-absolute path will be + prepended with the LyX document directory. + * USER INTERFACE