]> git.lyx.org Git - features.git/commitdiff
Backport the TEXINPUTS prefix feature. This should also fix bug #1751.
authorEnrico Forestieri <forenr@lyx.org>
Fri, 13 May 2011 23:14:46 +0000 (23:14 +0000)
committerEnrico Forestieri <forenr@lyx.org>
Fri, 13 May 2011 23:14:46 +0000 (23:14 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/branches/BRANCH_2_0_X@38746 a592a061-630c-0410-9148-cb99ea01b6c8

20 files changed:
src/Buffer.cpp
src/Converter.cpp
src/Format.cpp
src/LaTeX.cpp
src/LaTeX.h
src/LyXRC.cpp
src/LyXRC.h
src/VCBackend.cpp
src/frontends/qt4/GuiPrefs.cpp
src/frontends/qt4/ui/PrefPathsUi.ui
src/support/Systemcall.cpp
src/support/Systemcall.h
src/support/SystemcallPrivate.h
src/support/filetools.cpp
src/support/filetools.h
src/support/os.h
src/support/os_cygwin.cpp
src/support/os_unix.cpp
src/support/os_win32.cpp
status.20x

index f51084e8ef2ebf7db43bf46aea033c1c736cc240..47c82ccb7ecc0f6d8d53d0778a3910c3beaa02ff 100644 (file)
@@ -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) 
index 087b0b6af30494044df806eb168b5106069215bf..ff1d7093bf53d58554d88fdf79bc8ecad49ae883 100644 (file)
@@ -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);
index ec61b84387ea2a5c620f8d2e1ddf380ed13a0fd2..cc85b8500008165cb586f6c2ebccb2fb80fefaf3 100644 (file)
@@ -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;
index 1596ba1e8298e3c9611eb366710e27c37c481711..f1d7b1a779e4c05598268ac6ab36034f07ed5418 100644 (file)
@@ -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<AuxInfo> 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;
index 85088209caa9bda093286921bb2df03bfe9fe400..4d1c3356d8dde4ad44eaf4bd153c800ee88b9113 100644 (file)
@@ -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;
 
index 20daf4ac2059d1647f9c0437da16bdb5fc00d1f7..983eca3af5e1f68f78fb6dea87a0a11898beb6cc 100644 (file)
@@ -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;
index e8e4ee16db7af9310e793b14d6dc7339010736b1..9b067da329c1905687178c779a2c780c93b1e9a8 100644 (file)
@@ -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
index bc47719480488acfadb71e80ff61652253c713ed..342584284a8ef7ea1ca5f93d753e7751c54d76eb 100644 (file)
@@ -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);
 }
 
 
index dfac183249588a0d33e74b2fe4107c0d8ae8ba12..24b9a47f6802d33fa3f3797b3321eb333ab56bdb 100644 (file)
@@ -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)));
 }
index cab4cba8c0d4c9bee00db47570037d1fba85520f..b1792c5328bec6e791d998a183475d3e289d8359 100644 (file)
@@ -19,7 +19,7 @@
    <property name="spacing" >
     <number>6</number>
    </property>
-   <item row="11" column="0" colspan="3" >
+   <item row="12" column="0" colspan="3" >
     <spacer>
      <property name="orientation" >
       <enum>Qt::Vertical</enum>
     </widget>
    </item>
    <item row="10" column="1" colspan="2" >
-    <widget class="QLineEdit" name="pathPrefixED" />
+    <widget class="QLineEdit" name="pathPrefixED">
+     <property name="toolTip">
+      <string>Specify those directories which should be prepended to the PATH environment variable.&#x0a;Use the OS native format.</string>
+     </property>
+    </widget>
+   </item>
+   <item row="11" column="0">
+    <widget class="QLabel" name="texinputsPrefixLA">
+     <property name="text">
+      <string>TEX&amp;INPUTS prefix:</string>
+     </property>
+     <property name="buddy">
+      <cstring>texinputsPrefixED</cstring>
+     </property>
+    </widget>
+   </item>
+   <item row="11" column="1" colspan="2">
+    <widget class="QLineEdit" name="texinputsPrefixED">
+     <property name="toolTip">
+      <string>Specify those directories which should be prepended to the TEXINPUTS environment variable.&#x0a;A '.' represents the current document directory. Use the OS native format.</string>
+     </property>
+    </widget>
    </item>
    <item row="6" column="2" >
     <widget class="QPushButton" name="thesaurusDirPB" >
index 8cedb09a339075a8480a15e57aa28f46a34ad1e6..0753c590c8c0b5fe3b0454a6a5c2e1c9aa5a4f18 100644 (file)
@@ -14,6 +14,8 @@
 #include <config.h>
 
 #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 <cstdlib>
 #include <iostream>
@@ -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_);
        }
index 6d7d708e057e4e7eb1e4db4d1d6534fc2e9c5809..71e4c6237d4bd218fc3695dbf27dffaa350854a5 100644 (file)
@@ -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
index c8e3aa734c500c97be01555e419305922caba6ec..c0a4c7755a66c016b902ff4bec941f178a23a235 100644 (file)
@@ -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();
 
index 10387de4221e4cdb5fc82dbf730be4f86995f96f..dbf91ee59e10c7fd89e45e1a6f40b13b2727b776 100644 (file)
@@ -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,
index cd25d472006ada070acbc892d97c92f4143b6337..001c0f3ddc1476e80fb99677868fd82cfee7d097 100644 (file)
@@ -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.
  */
index 8d1744bf7e6ee7a3d38bf9963edce61f2bbdbf7f..d66173b1a73e6e50d35a019e577e2b346ae7ca52 100644 (file)
@@ -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.
index 6f5d57fdaf631f96ff640b03819664d945b71f97..389b4e2f78d797a281624fbdeca8bed7e762317f 100644 (file)
 
 #include <config.h>
 
+#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 <windows.h>
 #include <io.h>
@@ -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<int>(ShellExecute(NULL, action,
-               win_path.c_str(), NULL, NULL, 1)) > 32;
+       bool success = reinterpret_cast<int>(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;
 }
 
 
index 8727cff2b7412645559e2307098159c8fd14a45f..b8a94b2c5680e8a194be628bad162afd56df8d3b 100644 (file)
 
 #include <config.h>
 
+#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
index 2caf085691278d098fbdcdbe0e54d54c4dc8c842..72bf218a04db6e3be44b629d2c8a78c71b91ce43 100644 (file)
 
 #include <config.h>
 
+#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<int>(ShellExecute(NULL, action,
+       bool success = reinterpret_cast<int>(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;
 }
 
 
index b7ab4254918e5002b02e0821323cd0c58cc80f7b..d50f923160d642817323a4209e41539d13da3e0a 100644 (file)
@@ -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