]> git.lyx.org Git - lyx.git/blobdiff - src/LaTeX.cpp
listerrors.lyx : Update a link.
[lyx.git] / src / LaTeX.cpp
index 6003772cbb4dd071a81f5bc13fe78e456ea74f9b..3b06c8e34c0ed936149331ba70ea71999486d777 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 "support/Systemcall.h"
 #include "support/os.h"
 
-#include <boost/regex.hpp>
+#include "support/regex.h"
 
 #include <fstream>
+#include <stack>
 
-using boost::regex;
-using boost::smatch;
 
 using namespace std;
 using namespace lyx::support;
@@ -50,8 +49,6 @@ namespace os = support::os;
 //   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
 
 namespace {
@@ -68,23 +65,24 @@ docstring runMessage(unsigned int count)
  */
 
 void TeXErrors::insertError(int line, docstring const & error_desc,
-                           docstring const & error_text)
+                           docstring const & error_text,
+                           string const & child_name)
 {
-       Error newerr(line, error_desc, error_text);
+       Error newerr(line, error_desc, error_text, child_name);
        errors.push_back(newerr);
 }
 
 
-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);
 }
@@ -95,18 +93,18 @@ bool operator!=(Aux_Info const & a, Aux_Info 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 ?
-               depfile = FileName(file.absFilename() + ".dep-pdf");
+               depfile = FileName(file.absFileName() + ".dep-pdf");
                output_file =
-                       FileName(changeExtension(file.absFilename(), ".pdf"));
+                       FileName(changeExtension(file.absFileName(), ".pdf"));
        } else {
-               depfile = FileName(file.absFilename() + ".dep");
+               depfile = FileName(file.absFileName() + ".dep");
                output_file =
-                       FileName(changeExtension(file.absFilename(), ".dvi"));
+                       FileName(changeExtension(file.absFileName(), ".dvi"));
        }
 }
 
@@ -123,23 +121,27 @@ void LaTeX::deleteFilesOnError() const
        // but the reason for the error might be in a generated file...
 
        // bibtex file
-       FileName const bbl(changeExtension(file.absFilename(), ".bbl"));
+       FileName const bbl(changeExtension(file.absFileName(), ".bbl"));
        bbl.removeFile();
 
+       // biber file
+       FileName const bcf(changeExtension(file.absFileName(), ".bcf"));
+       bcf.removeFile();
+
        // makeindex file
-       FileName const ind(changeExtension(file.absFilename(), ".ind"));
+       FileName const ind(changeExtension(file.absFileName(), ".ind"));
        ind.removeFile();
 
        // nomencl file
-       FileName const nls(changeExtension(file.absFilename(), ".nls"));
+       FileName const nls(changeExtension(file.absFileName(), ".nls"));
        nls.removeFile();
 
        // nomencl file (old version of the package)
-       FileName const gls(changeExtension(file.absFilename(), ".gls"));
+       FileName const gls(changeExtension(file.absFileName(), ".gls"));
        gls.removeFile();
 
        // Also remove the aux file
-       FileName const aux(changeExtension(file.absFilename(), ".aux"));
+       FileName const aux(changeExtension(file.absFileName(), ".aux"));
        aux.removeFile();
 }
 
@@ -148,7 +150,7 @@ int LaTeX::run(TeXErrors & terr)
        // We know that this function will only be run if the lyx buffer
        // has been changed. We also know that a newly written .tex file
        // is always different from the previous one because of the date
-       // in it. However it seems safe to run latex (at least) on time
+       // in it. However it seems safe to run latex (at least) one time
        // each time the .tex file changes.
 {
        int scanres = NO_ERRORS;
@@ -159,7 +161,7 @@ int LaTeX::run(TeXErrors & terr)
        bool rerun = false; // rerun requested
 
        // The class LaTeX does not know the temp path.
-       theBufferList().updateIncludedTeXfiles(FileName::getcwd().absFilename(),
+       theBufferList().updateIncludedTeXfiles(FileName::getcwd().absFileName(),
                runparams);
 
        // Never write the depfile if an error was encountered.
@@ -182,7 +184,7 @@ int LaTeX::run(TeXErrors & terr)
 
        bool had_depfile = depfile.exists();
        bool run_bibtex = false;
-       FileName const aux_file(changeExtension(file.absFilename(), "aux"));
+       FileName const aux_file(changeExtension(file.absFileName(), "aux"));
 
        if (had_depfile) {
                LYXERR(Debug::DEPEND, "Dependency file exists");
@@ -216,7 +218,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);
 
@@ -237,7 +239,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;
 
@@ -245,7 +247,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
@@ -254,7 +256,7 @@ 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"));
+       FileName const idxfile(changeExtension(file.absFileName(), ".idx"));
        rerun = idxfile.exists() && idxfile.isFileEmpty();
 
        // run makeindex
@@ -262,16 +264,22 @@ int LaTeX::run(TeXErrors & terr)
                // no checks for now
                LYXERR(Debug::LATEX, "Running MakeIndex.");
                message(_("Running Index Processor."));
-               // onlyFilename() is needed for cygwin
-               rerun |= runMakeIndex(onlyFilename(idxfile.absFilename()),
+               // onlyFileName() is needed for cygwin
+               rerun |= runMakeIndex(onlyFileName(idxfile.absFileName()),
                                runparams);
        }
-       FileName const nlofile(changeExtension(file.absFilename(), ".nlo"));
+       FileName const nlofile(changeExtension(file.absFileName(), ".nlo"));
        if (head.haschanged(nlofile))
-               rerun |= runMakeIndexNomencl(file, runparams, ".nlo", ".nls");
-       FileName const glofile(changeExtension(file.absFilename(), ".glo"));
+               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");
+
+       // check if we're using biber instead of bibtex
+       // biber writes no info to the aux file, so we just check
+       // if a bcf file exists (and if it was updated)
+       FileName const bcffile(changeExtension(file.absFileName(), ".bcf"));
+       biber |= head.exist(bcffile);
 
        // run bibtex
        // if (scanres & UNDEF_CIT || scanres & RERUN || run_bibtex)
@@ -283,7 +291,15 @@ 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);
+               if (biber) {
+                       // since biber writes no info to the aux file, we have
+                       // to parse the blg file (which only exists after biber
+                       // was first issued)
+                       FileName const blgfile(changeExtension(file.absFileName(), ".blg"));
+                       if (blgfile.exists())
+                               scanBlgFile(head);
+               }
        } 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
@@ -291,7 +307,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
@@ -301,7 +317,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;
@@ -322,9 +338,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.
@@ -336,18 +367,18 @@ int LaTeX::run(TeXErrors & terr)
                // no checks for now
                LYXERR(Debug::LATEX, "Running MakeIndex.");
                message(_("Running Index Processor."));
-               // onlyFilename() is needed for cygwin
-               rerun = runMakeIndex(onlyFilename(changeExtension(
-                               file.absFilename(), ".idx")), runparams);
+               // onlyFileName() is needed for cygwin
+               rerun = runMakeIndex(onlyFileName(changeExtension(
+                               file.absFileName(), ".idx")), runparams);
        }
 
        // 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:
@@ -385,56 +416,67 @@ int LaTeX::run(TeXErrors & terr)
 
 int LaTeX::startscript()
 {
-       // onlyFilename() is needed for cygwin
+       // onlyFileName() is needed for cygwin
        string tmp = cmd + ' '
-                    + quoteName(onlyFilename(file.toFilesystemEncoding()))
+                    + quoteName(onlyFileName(file.toFilesystemEncoding()))
                     + " > " + os::nulldev();
        Systemcall one;
-       return one.startscript(Systemcall::Wait, tmp);
+       return one.startscript(Systemcall::Wait, tmp, path);
 }
 
 
 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;
-       one.startscript(Systemcall::Wait, tmp);
+       one.startscript(Systemcall::Wait, tmp, path);
        return true;
 }
 
 
 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
-       tmp += quoteName(onlyFilename(changeExtension(file.absFilename(), nlo)));
+       // onlyFileName() is needed for cygwin
+       tmp += quoteName(onlyFileName(changeExtension(file.absFileName(), nlo)));
        tmp += " -o "
-               + onlyFilename(changeExtension(file.toFilesystemEncoding(), nls));
+               + onlyFileName(changeExtension(file.toFilesystemEncoding(), nls));
        Systemcall one;
-       one.startscript(Systemcall::Wait, tmp);
+       one.startscript(Systemcall::Wait, tmp, path);
        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));
 
-       string const basename = removeExtension(file.absFilename());
+       string const basename = removeExtension(file.absFileName());
        for (int i = 1; i < 1000; ++i) {
                FileName const file2(basename
                        + '.' + convert<string>(i)
@@ -447,16 +489,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);
 
@@ -508,15 +550,15 @@ 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.
        dep.remove_files_with_extension(".bib");
        dep.remove_files_with_extension(".bst");
-       //string aux = OnlyFilename(ChangeExtension(file, ".aux"));
+       //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) {
@@ -532,24 +574,36 @@ void LaTeX::updateBibtexDependencies(DepTable & dep,
                                dep.insert(file, true);
                }
        }
+
+       // biber writes nothing into the aux file.
+       // Instead, we have to scan the blg file
+       if (biber) {
+               scanBlgFile(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())
+               if (!biber && it->databases.empty())
                        continue;
                result = true;
 
-               string tmp = lyxrc.bibtex_command + " ";
-               // onlyFilename() is needed for cygwin
-               tmp += quoteName(onlyFilename(removeExtension(
-                               it->aux_file.absFilename())));
+               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())));
                Systemcall one;
-               one.startscript(Systemcall::Wait, tmp);
+               one.startscript(Systemcall::Wait, tmp, path);
        }
        // Return whether bibtex was run
        return result;
@@ -562,12 +616,19 @@ int LaTeX::scanLogFile(TeXErrors & terr)
        int line_count = 1;
        int retval = NO_ERRORS;
        string tmp =
-               onlyFilename(changeExtension(file.absFilename(), ".log"));
+               onlyFileName(changeExtension(file.absFileName(), ".log"));
        LYXERR(Debug::LATEX, "Log file: " << tmp);
        FileName const fn = FileName(makeAbsPath(tmp));
        ifstream ifs(fn.toFilesystemEncoding().c_str());
        bool fle_style = false;
        static regex file_line_error(".+\\.\\D+:[0-9]+: (.+)");
+       static regex child_file(".*([0-9]+[A-Za-z]*_.+\\.tex).*");
+       // Flag for 'File ended while scanning' message.
+       // We need to wait for subsequent processing.
+       string wait_for_error;
+       string child_name;
+       int pnest = 0;
+       stack <pair<string, int> > child;
 
        string token;
        while (getline(ifs, token)) {
@@ -584,6 +645,29 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                if (token.empty())
                        continue;
 
+               // Track child documents
+               for (size_t i = 0; i < token.length(); ++i) {
+                       if (token[i] == '(') {
+                               ++pnest;
+                               size_t j = token.find('(', i + 1);
+                               size_t len = j == string::npos
+                                               ? token.substr(i + 1).length()
+                                               : j - i - 1;
+                               if (regex_match(token.substr(i + 1, len),
+                                                       sub, child_file)) {
+                                       string const name = sub.str(1);
+                                       child.push(make_pair(name, pnest));
+                                       i += len;
+                               }
+                       } else if (token[i] == ')') {
+                               if (!child.empty()
+                                   && child.top().second == pnest)
+                                       child.pop();
+                               --pnest;
+                       }
+               }
+               child_name = child.empty() ? empty_string() : child.top().first;
+
                if (contains(token, "file:line:error style messages enabled"))
                        fle_style = true;
 
@@ -602,6 +686,10 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                                   && contains(token, "undefined")) {
                                retval |= ERROR_RERUN;
                                LYXERR(Debug::LATEX, "Force rerun.");
+                       // package etaremune
+                       } else if (contains(token, "Etaremune labels have changed")) {
+                               retval |= ERROR_RERUN;
+                               LYXERR(Debug::LATEX, "Force rerun.");
                        } else if (contains(token, "Citation")
                                   && contains(token, "on page")
                                   && contains(token, "undefined")) {
@@ -619,13 +707,23 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                                }
                        } else if (contains(token, "run BibTeX")) {
                                retval |= UNDEF_CIT;
+                       } else if (contains(token, "run Biber")) {
+                               retval |= UNDEF_CIT;
+                               biber = true;
                        } else if (contains(token, "Rerun LaTeX") ||
+                                  contains(token, "Please rerun LaTeX") ||
                                   contains(token, "Rerun to get")) {
                                // at least longtable.sty and bibtopic.sty
                                // might use this.
                                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")) {
@@ -633,8 +731,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.
 
@@ -646,12 +746,52 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                                desc = sub.str();
                        if (contains(token, "LaTeX Error:"))
                                retval |= LATEX_ERROR;
+
+                       if (prefixIs(token, "! File ended while scanning")){
+                               if (prefixIs(token, "! File ended while scanning use of \\Hy@setref@link.")){
+                                       // bug 7344. We must rerun LaTeX if hyperref has been toggled.
+                                       retval |= ERROR_RERUN;
+                                       LYXERR(Debug::LATEX, "Force rerun.");
+                               } else {
+                                       // bug 6445. At this point its not clear we finish with error.
+                                       wait_for_error = desc;
+                                       continue;
+                               }
+                       }
+
+                       if (prefixIs(token, "! Paragraph ended before \\Hy@setref@link was complete.")){
+                                       // bug 7344. We must rerun LaTeX if hyperref has been toggled.
+                                       retval |= ERROR_RERUN;
+                                       LYXERR(Debug::LATEX, "Force rerun.");
+                       }
+
+                       if (!wait_for_error.empty() && prefixIs(token, "! Emergency stop.")){
+                               retval |= LATEX_ERROR;
+                               string errstr;
+                               int count = 0;
+                               errstr = wait_for_error;
+                               do {
+                                       if (!getline(ifs, tmp))
+                                               break;
+                                       tmp = rtrim(tmp, "\r");
+                                       errstr += "\n" + tmp;
+                                       if (++count > 5)
+                                               break;
+                               } while (!contains(tmp, "(job aborted"));
+
+                               terr.insertError(0,
+                                                from_local8bit("Emergency stop"),
+                                                from_local8bit(errstr),
+                                                child_name);
+                       }
+
                        // get the next line
                        string tmp;
                        int count = 0;
                        do {
                                if (!getline(ifs, tmp))
                                        break;
+                               tmp = rtrim(tmp, "\r");
                                if (++count > 10)
                                        break;
                        } while (!prefixIs(tmp, "l."));
@@ -670,6 +810,7 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                                string errstr(tmp, tmp.find(' '));
                                errstr += '\n';
                                getline(ifs, tmp);
+                               tmp = rtrim(tmp, "\r");
                                while (!contains(errstr, "l.")
                                       && !tmp.empty()
                                       && !prefixIs(tmp, "! ")
@@ -677,6 +818,7 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                                        errstr += tmp;
                                        errstr += "\n";
                                        getline(ifs, tmp);
+                                       tmp = rtrim(tmp, "\r");
                                }
                                LYXERR(Debug::LATEX, "line: " << line << '\n'
                                        << "Desc: " << desc << '\n' << "Text: " << errstr);
@@ -697,7 +839,8 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                                        // assume here it can be wrong.
                                        terr.insertError(line,
                                                         from_local8bit(desc),
-                                                        from_local8bit(errstr));
+                                                        from_local8bit(errstr),
+                                                        child_name);
                                        ++num_errors;
                                }
                        }
@@ -717,6 +860,14 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                        } else if (contains(token, "That makes 100 errors")) {
                                // More than 100 errors were reprted
                                retval |= TOO_MANY_ERRORS;
+                       } else if (prefixIs(token, "!pdfTeX error:")){
+                               // otherwise we dont catch e.g.:
+                               // !pdfTeX error: pdflatex (file feyn10): Font feyn10 at 600 not found
+                               retval |= ERRORS;
+                                       terr.insertError(0,
+                                                        from_local8bit("pdfTeX Error"),
+                                                        from_local8bit(token),
+                                                        child_name);
                        }
                }
        }
@@ -753,12 +904,13 @@ bool handleFoundFile(string const & ff, DepTable & head)
        // (1) foundfile is an
        //     absolute path and should
        //     be inserted.
-       FileName absname(foundfile);
-       if (absname.isAbsolute()) {
+       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.
+               absname.set(foundfile);
                if (!insertIfExists(absname, head)) {
                        // check for spaces
                        string strippedfile = foundfile;
@@ -780,7 +932,7 @@ bool handleFoundFile(string const & ff, DepTable & head)
                }
        }
 
-       string onlyfile = onlyFilename(foundfile);
+       string onlyfile = onlyFileName(foundfile);
        absname = makeAbsPath(onlyfile);
 
        // check for spaces
@@ -800,7 +952,7 @@ bool handleFoundFile(string const & ff, DepTable & head)
                        string const stripoff =
                                rsplit(foundfile, strippedfile, ' ');
                        foundfile = strippedfile;
-                       onlyfile = onlyFilename(strippedfile);
+                       onlyfile = onlyFileName(strippedfile);
                        absname = makeAbsPath(onlyfile);
                }
        }
@@ -851,7 +1003,7 @@ void LaTeX::deplog(DepTable & head)
        // entered into the dependency file.
 
        string const logfile =
-               onlyFilename(changeExtension(file.absFilename(), ".log"));
+               onlyFileName(changeExtension(file.absFileName(), ".log"));
 
        static regex const reg1("File: (.+).*");
        static regex const reg2("No file (.+)(.).*");
@@ -879,7 +1031,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;
@@ -896,6 +1048,10 @@ void LaTeX::deplog(DepTable & head)
                        continue;
                }
 
+               // FIXME UNICODE: We assume that the file names in the log
+               // file are in the file system encoding.
+               token = to_utf8(from_filesystem8bit(token));
+
                // Sometimes, filenames are broken across lines.
                // We care for that and save suspicious lines.
                // Here we exclude some cases where we are sure
@@ -925,10 +1081,6 @@ void LaTeX::deplog(DepTable & head)
 
                smatch sub;
 
-               // FIXME UNICODE: We assume that the file names in the log
-               // file are in the file system encoding.
-               token = to_utf8(from_filesystem8bit(token));
-
                // (1) "File: file.ext"
                if (regex_match(token, sub, reg1)) {
                        // check for dot
@@ -936,7 +1088,7 @@ void LaTeX::deplog(DepTable & head)
                        // However, ...
                        if (suffixIs(token, ")"))
                                // no line break for sure
-                               // pretend we've been succesfully searching
+                               // pretend we've been successfully searching
                                found_file = true;
                // (2) "No file file.ext"
                } else if (regex_match(token, sub, reg2)) {
@@ -973,11 +1125,11 @@ void LaTeX::deplog(DepTable & head)
                        found_file = checkLineBreak(sub.str(1), head);
                // (7) "\tf@toc=\write<nr>" (for MikTeX)
                else if (regex_match(token, sub, miktexTocReg))
-                       found_file = handleFoundFile(onlyFilename(changeExtension(
-                                               file.absFilename(), ".toc")), head);
+                       found_file = handleFoundFile(onlyFileName(changeExtension(
+                                               file.absFileName(), ".toc")), head);
                else
                        // not found, but we won't check further
-                       // pretend we've been succesfully searching
+                       // pretend we've been successfully searching
                        found_file = true;
 
                // (8) "(file.ext"
@@ -987,7 +1139,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();
@@ -1016,7 +1168,7 @@ void LaTeX::deplog(DepTable & head)
                                        // we have a closing bracket, so the content
                                        // is not a file name.
                                        // no need to investigate further
-                                       // pretend we've been succesfully searching
+                                       // pretend we've been successfully searching
                                        first = what[0].second;
                                        found_file = true;
                                }
@@ -1037,4 +1189,30 @@ void LaTeX::deplog(DepTable & head)
 }
 
 
+void LaTeX::scanBlgFile(DepTable & dep)
+{
+       FileName const blg_file(changeExtension(file.absFileName(), "blg"));
+       LYXERR(Debug::LATEX, "Scanning blg file: " << blg_file);
+
+       ifstream ifs(blg_file.toFilesystemEncoding().c_str());
+       string token;
+       static regex const reg1(".*Found bibtex data file '([^']+).*");
+
+       while (getline(ifs, token)) {
+               token = rtrim(token, "\r");
+               smatch sub;
+               // FIXME UNICODE: We assume that citation keys and filenames
+               // in the aux file are in the file system encoding.
+               token = to_utf8(from_filesystem8bit(token));
+               if (regex_match(token, sub, reg1)) {
+                       string data = sub.str(1);
+                       if (!data.empty()) {
+                               LYXERR(Debug::LATEX, "Found bib file: " << data);
+                               handleFoundFile(data, dep);
+                       }
+               }
+       } 
+}
+
+
 } // namespace lyx