]> git.lyx.org Git - lyx.git/blobdiff - src/LaTeX.cpp
MathML for InsetMathBig.
[lyx.git] / src / LaTeX.cpp
index 7c9d8e077862c9d1eb5386ebff63f73b34101ec5..49968ffdc8a6884995b4f53ff166c66fe09b7b05 100644 (file)
@@ -4,11 +4,11 @@
  * Licence details can be found in the file COPYING.
  *
  * \author Alfredo Braunstein
- * \author Lars Gullik Bjønnes
+ * \author Lars Gullik Bjønnes
  * \author Jean-Marc Lasgouttes
  * \author Angus Leeming
  * \author Dekel Tsur
- * \author Jürgen Spitzmüller
+ * \author Jürgen Spitzmüller
  *
  * Full author contact details are available in file CREDITS.
  */
 
 #include "BufferList.h"
 #include "LaTeX.h"
-#include "gettext.h"
 #include "LyXRC.h"
-#include "debug.h"
 #include "DepTable.h"
 
-#include "support/filetools.h"
+#include "support/debug.h"
 #include "support/convert.h"
+#include "support/FileName.h"
+#include "support/filetools.h"
+#include "support/gettext.h"
 #include "support/lstrings.h"
-#include "support/lyxlib.h"
 #include "support/Systemcall.h"
 #include "support/os.h"
 
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
 #include <boost/regex.hpp>
 
 #include <fstream>
 using boost::regex;
 using boost::smatch;
 
-#ifndef CXX_GLOBAL_CSTD
-using std::sscanf;
-#endif
-
-using std::endl;
-using std::getline;
-using std::string;
-using std::ifstream;
-using std::set;
-using std::vector;
-
+using namespace std;
+using namespace lyx::support;
 
 namespace lyx {
 
-using support::absolutePath;
-using support::bformat;
-using support::changeExtension;
-using support::contains;
-using support::FileName;
-using support::findtexfile;
-using support::getcwd;
-using support::makeAbsPath;
-using support::onlyFilename;
-using support::prefixIs;
-using support::quoteName;
-using support::removeExtension;
-using support::rtrim;
-using support::rsplit;
-using support::split;
-using support::subst;
-using support::suffixIs;
-using support::Systemcall;
-using support::unlink;
-using support::trim;
-
 namespace os = support::os;
-namespace fs = boost::filesystem;
 
 // TODO: in no particular order
 // - get rid of the call to
@@ -83,7 +50,6 @@ namespace fs = boost::filesystem;
 //   different way.
 // - the makeindex style files should be taken care of with
 //   the dependency mechanism.
-// - makeindex commandline options should be supported
 // - somewhere support viewing of bibtex and makeindex log files.
 // - we should perhaps also scan the bibtex log file
 
@@ -108,16 +74,16 @@ void TeXErrors::insertError(int line, docstring const & error_desc,
 }
 
 
-bool operator==(Aux_Info const & a, Aux_Info const & o)
+bool operator==(AuxInfo const & a, AuxInfo const & o)
 {
-       return a.aux_file == o.aux_file &&
-               a.citations == o.citations &&
-               a.databases == o.databases &&
-               a.styles == o.styles;
+       return a.aux_file == o.aux_file
+               && a.citations == o.citations
+               && a.databases == o.databases
+               && a.styles == o.styles;
 }
 
 
-bool operator!=(Aux_Info const & a, Aux_Info const & o)
+bool operator!=(AuxInfo const & a, AuxInfo const & o)
 {
        return !(a == o);
 }
@@ -151,29 +117,29 @@ void LaTeX::deleteFilesOnError() const
        // What files do we have to delete?
 
        // This will at least make latex do all the runs
-       unlink(depfile);
+       depfile.removeFile();
 
        // but the reason for the error might be in a generated file...
 
        // bibtex file
        FileName const bbl(changeExtension(file.absFilename(), ".bbl"));
-       unlink(bbl);
+       bbl.removeFile();
 
        // makeindex file
        FileName const ind(changeExtension(file.absFilename(), ".ind"));
-       unlink(ind);
+       ind.removeFile();
 
        // nomencl file
        FileName const nls(changeExtension(file.absFilename(), ".nls"));
-       unlink(nls);
+       nls.removeFile();
 
        // nomencl file (old version of the package)
        FileName const gls(changeExtension(file.absFilename(), ".gls"));
-       unlink(gls);
+       gls.removeFile();
 
        // Also remove the aux file
        FileName const aux(changeExtension(file.absFilename(), ".aux"));
-       unlink(aux);
+       aux.removeFile();
 }
 
 
@@ -192,7 +158,7 @@ int LaTeX::run(TeXErrors & terr)
        bool rerun = false; // rerun requested
 
        // The class LaTeX does not know the temp path.
-       theBufferList().updateIncludedTeXfiles(getcwd().absFilename(),
+       theBufferList().updateIncludedTeXfiles(FileName::getcwd().absFilename(),
                runparams);
 
        // Never write the depfile if an error was encountered.
@@ -249,7 +215,7 @@ int LaTeX::run(TeXErrors & terr)
        /// We scan the aux file even when had_depfile = false,
        /// because we can run pdflatex on the file after running latex on it,
        /// in which case we will not need to run bibtex again.
-       vector<Aux_Info> bibtex_info_old;
+       vector<AuxInfo> bibtex_info_old;
        if (!run_bibtex)
                bibtex_info_old = scanAuxFiles(aux_file);
 
@@ -270,7 +236,7 @@ int LaTeX::run(TeXErrors & terr)
                return scanres; // return on error
        }
 
-       vector<Aux_Info> const bibtex_info = scanAuxFiles(aux_file);
+       vector<AuxInfo> const bibtex_info = scanAuxFiles(aux_file);
        if (!run_bibtex && bibtex_info_old != bibtex_info)
                run_bibtex = true;
 
@@ -278,7 +244,7 @@ int LaTeX::run(TeXErrors & terr)
        deplog(head); // reads the latex log
        head.update();
 
-       // 0.5
+       // 1
        // At this point we must run external programs if needed.
        // makeindex will be run if a .idx file changed or was generated.
        // And if there were undefined citations or changes in references
@@ -288,23 +254,23 @@ int LaTeX::run(TeXErrors & terr)
        // memoir (at least) writes an empty *idx file in the first place.
        // A second latex run is needed.
        FileName const idxfile(changeExtension(file.absFilename(), ".idx"));
-       rerun = idxfile.exists() && fs::is_empty(idxfile.toFilesystemEncoding());
+       rerun = idxfile.exists() && idxfile.isFileEmpty();
 
        // run makeindex
        if (head.haschanged(idxfile)) {
                // no checks for now
                LYXERR(Debug::LATEX, "Running MakeIndex.");
-               message(_("Running MakeIndex."));
+               message(_("Running Index Processor."));
                // onlyFilename() is needed for cygwin
                rerun |= runMakeIndex(onlyFilename(idxfile.absFilename()),
                                runparams);
        }
        FileName const nlofile(changeExtension(file.absFilename(), ".nlo"));
        if (head.haschanged(nlofile))
-               rerun |= runMakeIndexNomencl(file, runparams, ".nlo", ".nls");
+               rerun |= runMakeIndexNomencl(file, ".nlo", ".nls");
        FileName const glofile(changeExtension(file.absFilename(), ".glo"));
        if (head.haschanged(glofile))
-               rerun |= runMakeIndexNomencl(file, runparams, ".glo", ".gls");
+               rerun |= runMakeIndexNomencl(file, ".glo", ".gls");
 
        // run bibtex
        // if (scanres & UNDEF_CIT || scanres & RERUN || run_bibtex)
@@ -316,7 +282,7 @@ int LaTeX::run(TeXErrors & terr)
                LYXERR(Debug::LATEX, "Running BibTeX.");
                message(_("Running BibTeX."));
                updateBibtexDependencies(head, bibtex_info);
-               rerun |= runBibTeX(bibtex_info);
+               rerun |= runBibTeX(bibtex_info, runparams);
        } else if (!had_depfile) {
                /// If we run pdflatex on the file after running latex on it,
                /// then we do not need to run bibtex, but we do need to
@@ -324,7 +290,7 @@ int LaTeX::run(TeXErrors & terr)
                updateBibtexDependencies(head, bibtex_info);
        }
 
-       // 1
+       // 2
        // we know on this point that latex has been run once (or we just
        // returned) and the question now is to decide if we need to run
        // it any more. This is done by asking if any of the files in the
@@ -334,7 +300,7 @@ int LaTeX::run(TeXErrors & terr)
        //             run latex once more and
        //             update the dependency structure
        //     -> if not changed:
-       //             we does nothing at this point
+       //             we do nothing at this point
        //
        if (rerun || head.sumchange()) {
                rerun = false;
@@ -355,9 +321,24 @@ int LaTeX::run(TeXErrors & terr)
        } else {
                LYXERR(Debug::DEPEND, "Dep. file has NOT changed");
        }
+       
+       // 3
+       // rerun bibtex?
+       // Complex bibliography packages such as Biblatex require
+       // an additional bibtex cycle sometimes.
+       if (scanres & UNDEF_CIT) {
+               // Here we must scan the .aux file and look for
+               // "\bibdata" and/or "\bibstyle". If one of those
+               // tags is found -> run bibtex and set rerun = true;
+               // no checks for now
+               LYXERR(Debug::LATEX, "Running BibTeX.");
+               message(_("Running BibTeX."));
+               updateBibtexDependencies(head, bibtex_info);
+               rerun |= runBibTeX(bibtex_info, runparams);
+       }
 
-       // 1.5
-       // The inclusion of files generated by external programs like
+       // 4
+       // The inclusion of files generated by external programs such as
        // makeindex or bibtex might have done changes to pagenumbering,
        // etc. And because of this we must run the external programs
        // again to make sure everything is redone correctly.
@@ -368,7 +349,7 @@ int LaTeX::run(TeXErrors & terr)
        if (head.haschanged(idxfile)) {
                // no checks for now
                LYXERR(Debug::LATEX, "Running MakeIndex.");
-               message(_("Running MakeIndex."));
+               message(_("Running Index Processor."));
                // onlyFilename() is needed for cygwin
                rerun = runMakeIndex(onlyFilename(changeExtension(
                                file.absFilename(), ".idx")), runparams);
@@ -376,11 +357,11 @@ int LaTeX::run(TeXErrors & terr)
 
        // I am not pretty sure if need this twice.
        if (head.haschanged(nlofile))
-               rerun |= runMakeIndexNomencl(file, runparams, ".nlo", ".nls");
+               rerun |= runMakeIndexNomencl(file, ".nlo", ".nls");
        if (head.haschanged(glofile))
-               rerun |= runMakeIndexNomencl(file, runparams, ".glo", ".gls");
+               rerun |= runMakeIndexNomencl(file, ".glo", ".gls");
 
-       // 2
+       // 5
        // we will only run latex more if the log file asks for it.
        // or if the sumchange() is true.
        //     -> rerun asked for:
@@ -430,11 +411,23 @@ int LaTeX::startscript()
 bool LaTeX::runMakeIndex(string const & f, OutputParams const & runparams,
                         string const & params)
 {
+       string tmp = runparams.use_japanese ?
+               lyxrc.jindex_command : lyxrc.index_command;
+       
+       if (!runparams.index_command.empty())
+               tmp = runparams.index_command;
+
        LYXERR(Debug::LATEX,
-               "idx file has been made, running makeindex on file " << f);
-       string tmp = lyxrc.index_command + ' ';
+               "idx file has been made, running index processor ("
+               << tmp << ") on file " << f);
 
        tmp = subst(tmp, "$$lang", runparams.document_language);
+       if (runparams.use_indices) {
+               tmp = lyxrc.splitindex_command + " -m " + quoteName(tmp);
+               LYXERR(Debug::LATEX,
+               "Multiple indices. Using splitindex command: " << tmp);
+       }
+       tmp += ' ';
        tmp += quoteName(f);
        tmp += params;
        Systemcall one;
@@ -444,24 +437,25 @@ bool LaTeX::runMakeIndex(string const & f, OutputParams const & runparams,
 
 
 bool LaTeX::runMakeIndexNomencl(FileName const & file,
-               OutputParams const & runparams,
                string const & nlo, string const & nls)
 {
        LYXERR(Debug::LATEX, "Running MakeIndex for nomencl.");
        message(_("Running MakeIndex for nomencl."));
+       string tmp = lyxrc.nomencl_command + ' ';
        // onlyFilename() is needed for cygwin
-       string const nomenclstr = " -s nomencl.ist -o "
+       tmp += quoteName(onlyFilename(changeExtension(file.absFilename(), nlo)));
+       tmp += " -o "
                + onlyFilename(changeExtension(file.toFilesystemEncoding(), nls));
-       return runMakeIndex(
-                       onlyFilename(changeExtension(file.absFilename(), nlo)),
-                       runparams, nomenclstr);
+       Systemcall one;
+       one.startscript(Systemcall::Wait, tmp);
+       return true;
 }
 
 
-vector<Aux_Info> const
+vector<AuxInfo> const
 LaTeX::scanAuxFiles(FileName const & file)
 {
-       vector<Aux_Info> result;
+       vector<AuxInfo> result;
 
        result.push_back(scanAuxFile(file));
 
@@ -478,16 +472,16 @@ LaTeX::scanAuxFiles(FileName const & file)
 }
 
 
-Aux_Info const LaTeX::scanAuxFile(FileName const & file)
+AuxInfo const LaTeX::scanAuxFile(FileName const & file)
 {
-       Aux_Info result;
+       AuxInfo result;
        result.aux_file = file;
        scanAuxFile(file, result);
        return result;
 }
 
 
-void LaTeX::scanAuxFile(FileName const & file, Aux_Info & aux_info)
+void LaTeX::scanAuxFile(FileName const & file, AuxInfo & aux_info)
 {
        LYXERR(Debug::LATEX, "Scanning aux file: " << file);
 
@@ -539,7 +533,7 @@ void LaTeX::scanAuxFile(FileName const & file, Aux_Info & aux_info)
 
 
 void LaTeX::updateBibtexDependencies(DepTable & dep,
-                                    vector<Aux_Info> const & bibtex_info)
+                                    vector<AuxInfo> const & bibtex_info)
 {
        // Since a run of Bibtex mandates more latex runs it is ok to
        // remove all ".bib" and ".bst" files.
@@ -547,7 +541,7 @@ void LaTeX::updateBibtexDependencies(DepTable & dep,
        dep.remove_files_with_extension(".bst");
        //string aux = OnlyFilename(ChangeExtension(file, ".aux"));
 
-       for (vector<Aux_Info>::const_iterator it = bibtex_info.begin();
+       for (vector<AuxInfo>::const_iterator it = bibtex_info.begin();
             it != bibtex_info.end(); ++it) {
                for (set<string>::const_iterator it2 = it->databases.begin();
                     it2 != it->databases.end(); ++it2) {
@@ -566,16 +560,22 @@ void LaTeX::updateBibtexDependencies(DepTable & dep,
 }
 
 
-bool LaTeX::runBibTeX(vector<Aux_Info> const & bibtex_info)
+bool LaTeX::runBibTeX(vector<AuxInfo> const & bibtex_info,
+                     OutputParams const & runparams)
 {
        bool result = false;
-       for (vector<Aux_Info>::const_iterator it = bibtex_info.begin();
+       for (vector<AuxInfo>::const_iterator it = bibtex_info.begin();
             it != bibtex_info.end(); ++it) {
                if (it->databases.empty())
                        continue;
                result = true;
 
-               string tmp = lyxrc.bibtex_command + " ";
+               string tmp = runparams.use_japanese ?
+                       lyxrc.jbibtex_command : lyxrc.bibtex_command;
+
+               if (!runparams.bibtex_command.empty())
+                       tmp = runparams.bibtex_command;
+               tmp += " ";
                // onlyFilename() is needed for cygwin
                tmp += quoteName(onlyFilename(removeExtension(
                                it->aux_file.absFilename())));
@@ -627,6 +627,12 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                        if (contains(token, "Rerun to get cross-references")) {
                                retval |= RERUN;
                                LYXERR(Debug::LATEX, "We should rerun.");
+                       // package clefval needs 2 latex runs before bibtex
+                       } else if (contains(token, "Value of")
+                                  && contains(token, "on page")
+                                  && contains(token, "undefined")) {
+                               retval |= ERROR_RERUN;
+                               LYXERR(Debug::LATEX, "Force rerun.");
                        } else if (contains(token, "Citation")
                                   && contains(token, "on page")
                                   && contains(token, "undefined")) {
@@ -651,6 +657,12 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                                LYXERR(Debug::LATEX, "We should rerun.");
                                retval |= RERUN;
                        }
+               } else if (prefixIs(token, "LETTRE WARNING:")) {
+                       if (contains(token, "veuillez recompiler")) {
+                               // lettre.cls
+                               LYXERR(Debug::LATEX, "We should rerun.");
+                               retval |= RERUN;
+                       }
                } else if (token[0] == '(') {
                        if (contains(token, "Rerun LaTeX") ||
                            contains(token, "Rerun to get")) {
@@ -658,8 +670,10 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                                LYXERR(Debug::LATEX, "We should rerun.");
                                retval |= RERUN;
                        }
-               } else if (prefixIs(token, "! ") ||
-                          fle_style && regex_match(token, sub, file_line_error)) {
+               } else if (prefixIs(token, "! ")
+                           || (fle_style
+                               && regex_match(token, sub, file_line_error)
+                               && !contains(token, "pdfTeX warning"))) {
                           // Ok, we have something that looks like a TeX Error
                           // but what do we really have.
 
@@ -778,12 +792,13 @@ bool handleFoundFile(string const & ff, DepTable & head)
        // (1) foundfile is an
        //     absolute path and should
        //     be inserted.
-       if (absolutePath(foundfile)) {
+       FileName absname;
+       if (FileName::isAbsolute(foundfile)) {
                LYXERR(Debug::DEPEND, "AbsolutePath file: " << foundfile);
                // On initial insert we want to do the update at once
                // since this file cannot be a file generated by
                // the latex run.
-               FileName absname(foundfile);
+               absname.set(foundfile);
                if (!insertIfExists(absname, head)) {
                        // check for spaces
                        string strippedfile = foundfile;
@@ -806,7 +821,7 @@ bool handleFoundFile(string const & ff, DepTable & head)
        }
 
        string onlyfile = onlyFilename(foundfile);
-       FileName absname(makeAbsPath(onlyfile));
+       absname = makeAbsPath(onlyfile);
 
        // check for spaces
        while (contains(foundfile, ' ')) {
@@ -904,7 +919,7 @@ void LaTeX::deplog(DepTable & head)
        string lastline;
        while (ifs) {
                // Ok, the scanning of files here is not sufficient.
-               // Sometimes files are named by "File: xxx" only
+               // Sometimes files are named by "File: xxx" only
                // So I think we should use some regexps to find files instead.
                // Note: all file names and paths might contains spaces.
                bool found_file = false;
@@ -1012,7 +1027,7 @@ void LaTeX::deplog(DepTable & head)
                // where "File: file.ext" would be skipped
                if (regex_match(token, sub, reg6)) {
                        // search for strings in (...)
-                       static regex reg6_1("\\(([^()]+)(.).*");
+                       static regex reg6_1("\\(([^()]+)(.)");
                        smatch what;
                        string::const_iterator first = token.begin();
                        string::const_iterator end = token.end();