X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FLaTeX.C;h=b8caf83b607aa2bf65056589af6a3ad41688edc2;hb=c68f3da771a54ef78bd309b8f1a81c374d2fea4c;hp=5c5a966eb4a19a452bde36066086b8889ba7b1bf;hpb=43b77ba2d722cdb8a9437926f839c1dcbf3c0b89;p=lyx.git diff --git a/src/LaTeX.C b/src/LaTeX.C index 5c5a966eb4..b8caf83b60 100644 --- a/src/LaTeX.C +++ b/src/LaTeX.C @@ -14,12 +14,13 @@ #include -#include "LaTeX.h" #include "bufferlist.h" +#include "LaTeX.h" #include "gettext.h" #include "lyxrc.h" #include "debug.h" #include "DepTable.h" + #include "support/filetools.h" #include "support/convert.h" #include "support/lstrings.h" @@ -32,24 +33,30 @@ #include -using lyx::support::absolutePath; -using lyx::support::bformat; -using lyx::support::changeExtension; -using lyx::support::contains; -using lyx::support::findtexfile; -using lyx::support::getcwd; -using lyx::support::onlyFilename; -using lyx::support::prefixIs; -using lyx::support::quoteName; -using lyx::support::rtrim; -using lyx::support::split; -using lyx::support::subst; -using lyx::support::suffixIs; -using lyx::support::Systemcall; -using lyx::support::unlink; -using lyx::support::trim; - -namespace os = lyx::support::os; + +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::split; +using support::subst; +using support::suffixIs; +using support::Systemcall; +using support::unlink; +using support::trim; + +namespace os = support::os; namespace fs = boost::filesystem; using boost::regex; @@ -68,7 +75,7 @@ using std::set; using std::vector; // TODO: in no particular order -// - get rid of the extern BufferList and the call to +// - get rid of the call to // BufferList::updateIncludedTeXfiles, this should either // be done before calling LaTeX::funcs or in a completely // different way. @@ -78,13 +85,11 @@ using std::vector; // - somewhere support viewing of bibtex and makeindex log files. // - we should perhaps also scan the bibtex log file -extern BufferList bufferlist; - namespace { -string runMessage(unsigned int count) +docstring runMessage(unsigned int count) { - return bformat(lyx::to_utf8(_("Waiting for LaTeX run number %1$d")), count); + return bformat(_("Waiting for LaTeX run number %1$d"), count); } } // anon namespace @@ -93,8 +98,8 @@ string runMessage(unsigned int count) * CLASS TEXERRORS */ -void TeXErrors::insertError(int line, string const & error_desc, - string const & error_text) +void TeXErrors::insertError(int line, docstring const & error_desc, + docstring const & error_text) { Error newerr(line, error_desc, error_text); errors.push_back(newerr); @@ -121,16 +126,16 @@ bool operator!=(Aux_Info const & a, Aux_Info const & o) */ LaTeX::LaTeX(string const & latex, OutputParams const & rp, - string const & f, string const & p) - : cmd(latex), file(f), path(p), runparams(rp) + FileName const & f) + : cmd(latex), file(f), runparams(rp) { num_errors = 0; - depfile = file + ".dep"; if (prefixIs(cmd, "pdf")) { // Do we use pdflatex ? - depfile += "-pdf"; - output_file = changeExtension(file,".pdf"); + depfile = FileName(file.absFilename() + ".dep-pdf"); + output_file = FileName(changeExtension(file.absFilename(), ".pdf")); } else { - output_file = changeExtension(file,".dvi"); + depfile = FileName(file.absFilename() + ".dep"); + output_file = FileName(changeExtension(file.absFilename(), ".dvi")); } } @@ -146,18 +151,20 @@ void LaTeX::deleteFilesOnError() const // but the reason for the error might be in a generated file... - string const ofname = onlyFilename(file); - // bibtex file - string const bbl = changeExtension(ofname, ".bbl"); + FileName const bbl(changeExtension(file.absFilename(), ".bbl")); unlink(bbl); // makeindex file - string const ind = changeExtension(ofname, ".ind"); + FileName const ind(changeExtension(file.absFilename(), ".ind")); unlink(ind); + // nomencl file + FileName const nls(changeExtension(file.absFilename(), ".nls")); + unlink(nls); + // Also remove the aux file - string const aux = changeExtension(ofname, ".aux"); + FileName const aux(changeExtension(file.absFilename(), ".aux")); unlink(aux); } @@ -177,7 +184,7 @@ int LaTeX::run(TeXErrors & terr) bool rerun = false; // rerun requested // The class LaTeX does not know the temp path. - bufferlist.updateIncludedTeXfiles(getcwd(), runparams); + theBufferList().updateIncludedTeXfiles(getcwd().absFilename(), runparams); // Never write the depfile if an error was encountered. @@ -197,9 +204,9 @@ int LaTeX::run(TeXErrors & terr) // remake the dependency file. // - bool had_depfile = fs::exists(depfile); + bool had_depfile = fs::exists(depfile.toFilesystemEncoding()); bool run_bibtex = false; - string aux_file = onlyFilename(changeExtension(file, "aux")); + FileName const aux_file(changeExtension(file.absFilename(), "aux")); if (had_depfile) { lyxerr[Debug::DEPEND] << "Dependency file exists" << endl; @@ -213,7 +220,7 @@ int LaTeX::run(TeXErrors & terr) // Can't just check if anything has changed because it might have aborted // on error last time... in which cas we need to re-run latex // and collect the error messages (even if they are the same). - if (!fs::exists(output_file)) { + if (!fs::exists(output_file.toFilesystemEncoding())) { lyxerr[Debug::DEPEND] << "re-running LaTeX because output file doesn't exist." << endl; } else if (!head.sumchange()) { @@ -271,15 +278,24 @@ int LaTeX::run(TeXErrors & terr) // memoir (at least) writes an empty *idx file in the first place. // A second latex run is needed. - rerun = fs::exists(changeExtension(file, ".idx")) - && fs::is_empty(changeExtension(file, ".idx")); + FileName const idxfile(changeExtension(file.absFilename(), ".idx")); + rerun = fs::exists(idxfile.toFilesystemEncoding()) && + fs::is_empty(idxfile.toFilesystemEncoding()); // run makeindex - if (head.haschanged(onlyFilename(changeExtension(file, ".idx")))) { + if (head.haschanged(idxfile)) { // no checks for now lyxerr[Debug::LATEX] << "Running MakeIndex." << endl; - message(lyx::to_utf8(_("Running MakeIndex."))); - rerun |= runMakeIndex(onlyFilename(changeExtension(file, ".idx")), runparams); + message(_("Running MakeIndex.")); + // onlyFilename() is needed for cygwin + rerun |= runMakeIndex(onlyFilename(idxfile.absFilename()), runparams); + } + if (head.haschanged(FileName(changeExtension(file.absFilename(), ".nlo")))) { + lyxerr[Debug::LATEX] << "Running MakeIndex for nomencl." << endl; + message(_("Running MakeIndex for nomencl.")); + // onlyFilename() is needed for cygwin + string const nomenclstr = " -s nomencl.ist -o " + onlyFilename(changeExtension(file.toFilesystemEncoding(), ".nls")); + rerun |= runMakeIndex(onlyFilename(changeExtension(file.absFilename(), ".nlo")), runparams, nomenclstr); } // run bibtex @@ -290,7 +306,7 @@ int LaTeX::run(TeXErrors & terr) // tags is found -> run bibtex and set rerun = true; // no checks for now lyxerr[Debug::LATEX] << "Running BibTeX." << endl; - message(lyx::to_utf8(_("Running BibTeX."))); + message(_("Running BibTeX.")); updateBibtexDependencies(head, bibtex_info); rerun |= runBibTeX(bibtex_info); } else if (!had_depfile) { @@ -343,11 +359,21 @@ int LaTeX::run(TeXErrors & terr) // more after this. // run makeindex if the .idx has changed or was generated. - if (head.haschanged(onlyFilename(changeExtension(file, ".idx")))) { + if (head.haschanged(FileName(changeExtension(file.absFilename(), ".idx")))) { // no checks for now lyxerr[Debug::LATEX] << "Running MakeIndex." << endl; - message(lyx::to_utf8(_("Running MakeIndex."))); - rerun = runMakeIndex(onlyFilename(changeExtension(file, ".idx")), runparams); + message(_("Running MakeIndex.")); + // 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(FileName(changeExtension(file.absFilename(), ".nlo")))) { + lyxerr[Debug::LATEX] << "Running MakeIndex for nomencl." << endl; + message(_("Running MakeIndex for nomencl.")); + // onlyFilename() is needed for cygwin + string nomenclstr = " -s nomencl.ist -o " + onlyFilename(changeExtension(file.toFilesystemEncoding(), ".nls")); + rerun |= runMakeIndex(onlyFilename(changeExtension(file.absFilename(), ".nlo")), runparams, nomenclstr); } // 2 @@ -388,20 +414,24 @@ int LaTeX::run(TeXErrors & terr) int LaTeX::startscript() { - string tmp = cmd + ' ' + quoteName(file) + " > " + os::nulldev(); + // onlyFilename() is needed for cygwin + string tmp = cmd + ' ' + quoteName(onlyFilename(file.toFilesystemEncoding())) + " > " + os::nulldev(); Systemcall one; return one.startscript(Systemcall::Wait, tmp); } -bool LaTeX::runMakeIndex(string const & f, OutputParams const & runparams) +bool LaTeX::runMakeIndex(string const & f, OutputParams const & runparams, + string const & params) { - lyxerr[Debug::LATEX] << "idx file has been made," - " running makeindex on file " - << f << endl; - string tmp = lyxrc.index_command + " "; + lyxerr[Debug::LATEX] + << "idx file has been made, running makeindex on file " + << f << endl; + string tmp = lyxrc.index_command + ' '; + tmp = subst(tmp, "$$lang", runparams.document_language); tmp += quoteName(f); + tmp += params; Systemcall one; one.startscript(Systemcall::Wait, tmp); return true; @@ -409,17 +439,18 @@ bool LaTeX::runMakeIndex(string const & f, OutputParams const & runparams) vector const -LaTeX::scanAuxFiles(string const & file) +LaTeX::scanAuxFiles(FileName const & file) { vector result; result.push_back(scanAuxFile(file)); + string const basename = removeExtension(file.absFilename()); for (int i = 1; i < 1000; ++i) { - string const file2 = changeExtension(file, "") + FileName const file2(basename + '.' + convert(i) - + ".aux"; - if (!fs::exists(file2)) + + ".aux"); + if (!fs::exists(file2.toFilesystemEncoding())) break; result.push_back(scanAuxFile(file2)); } @@ -427,7 +458,7 @@ LaTeX::scanAuxFiles(string const & file) } -Aux_Info const LaTeX::scanAuxFile(string const & file) +Aux_Info const LaTeX::scanAuxFile(FileName const & file) { Aux_Info result; result.aux_file = file; @@ -436,11 +467,11 @@ Aux_Info const LaTeX::scanAuxFile(string const & file) } -void LaTeX::scanAuxFile(string const & file, Aux_Info & aux_info) +void LaTeX::scanAuxFile(FileName const & file, Aux_Info & aux_info) { lyxerr[Debug::LATEX] << "Scanning aux file: " << file << endl; - ifstream ifs(file.c_str()); + ifstream ifs(file.toFilesystemEncoding().c_str()); string token; static regex const reg1("\\\\citation\\{([^}]+)\\}"); static regex const reg2("\\\\bibdata\\{([^}]+)\\}"); @@ -450,6 +481,9 @@ void LaTeX::scanAuxFile(string const & file, Aux_Info & aux_info) 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); while (!data.empty()) { @@ -481,7 +515,7 @@ void LaTeX::scanAuxFile(string const & file, Aux_Info & aux_info) aux_info.styles.insert(style); } else if (regex_match(token, sub, reg4)) { string const file2 = sub.str(1); - scanAuxFile(file2, aux_info); + scanAuxFile(makeAbsPath(file2), aux_info); } } } @@ -500,14 +534,14 @@ void LaTeX::updateBibtexDependencies(DepTable & dep, it != bibtex_info.end(); ++it) { for (set::const_iterator it2 = it->databases.begin(); it2 != it->databases.end(); ++it2) { - string file = findtexfile(*it2, "bib"); + FileName const file = findtexfile(*it2, "bib"); if (!file.empty()) dep.insert(file, true); } for (set::const_iterator it2 = it->styles.begin(); it2 != it->styles.end(); ++it2) { - string file = findtexfile(*it2, "bst"); + FileName const file = findtexfile(*it2, "bst"); if (!file.empty()) dep.insert(file, true); } @@ -525,7 +559,8 @@ bool LaTeX::runBibTeX(vector const & bibtex_info) result = true; string tmp = lyxrc.bibtex_command + " "; - tmp += quoteName(onlyFilename(changeExtension(it->aux_file, string()))); + // onlyFilename() is needed for cygwin + tmp += quoteName(onlyFilename(removeExtension(it->aux_file.absFilename()))); Systemcall one; one.startscript(Systemcall::Wait, tmp); } @@ -539,9 +574,10 @@ int LaTeX::scanLogFile(TeXErrors & terr) int last_line = -1; int line_count = 1; int retval = NO_ERRORS; - string tmp = onlyFilename(changeExtension(file, ".log")); + string tmp = onlyFilename(changeExtension(file.absFilename(), ".log")); lyxerr[Debug::LATEX] << "Log file: " << tmp << endl; - ifstream ifs(tmp.c_str()); + FileName const fn = FileName(makeAbsPath(tmp)); + ifstream ifs(fn.toFilesystemEncoding().c_str()); string token; while (getline(ifs, token)) { @@ -648,7 +684,15 @@ int LaTeX::scanLogFile(TeXErrors & terr) last_line = line; } if (line_count <= 5) { - terr.insertError(line, desc, errstr); + // FIXME UNICODE + // We have no idea what the encoding of + // the log file is. + // It seems that the output from the + // latex compiler itself is pure ASCII, + // but it can include bits from the + // document, so whatever encoding we + // assume here it can be wrong. + terr.insertError(line, from_local8bit(desc), from_local8bit(errstr)); ++num_errors; } } @@ -698,19 +742,22 @@ void handleFoundFile(string const & ff, DepTable & head) lyxerr[Debug::DEPEND] << "AbsolutePath file: " << foundfile << endl; // On initial insert we want to do the update at once - // since this file can not be a file generated by + // since this file cannot be a file generated by // the latex run. - if (fs::exists(foundfile) && !fs::is_directory(foundfile)) - head.insert(foundfile, true); + FileName const absname(foundfile); + if (fs::exists(absname.toFilesystemEncoding()) && + !fs::is_directory(absname.toFilesystemEncoding())) + head.insert(absname, true); return; } string const onlyfile = onlyFilename(foundfile); + FileName const absname(makeAbsPath(onlyfile)); // (2) foundfile is in the tmpdir // insert it into head - if (fs::exists(onlyfile)) { + if (fs::exists(absname.toFilesystemEncoding())) { static regex unwanted("^.*\\.(aux|log|dvi|bbl|ind|glo)$"); if (regex_match(onlyfile, unwanted)) { lyxerr[Debug::DEPEND] @@ -726,13 +773,13 @@ void handleFoundFile(string const & ff, DepTable & head) << "Tmpdir TeX file: " << onlyfile << endl; - head.insert(onlyfile, true); + head.insert(absname, true); } else { lyxerr[Debug::DEPEND] << "In tmpdir file:" << onlyfile << endl; - head.insert(onlyfile); + head.insert(absname); } } else lyxerr[Debug::DEPEND] @@ -749,7 +796,7 @@ void LaTeX::deplog(DepTable & head) // files used by the LaTeX run. The files are then entered into the // dependency file. - string const logfile = onlyFilename(changeExtension(file, ".log")); + string const logfile = onlyFilename(changeExtension(file.absFilename(), ".log")); static regex reg1(".*\\([^)]+.*"); static regex reg2("File: ([^ ]+).*"); @@ -760,6 +807,7 @@ void LaTeX::deplog(DepTable & head) // but instead only a line like this into the log: // Writing index file sample.idx static regex reg5("Writing index file ([^ ]+).*"); + static regex regnomencl("Writing nomenclature file ([^ ]+).*"); // If a toc should be created, MikTex does not write a line like // \openout# = `sample.toc'. // but only a line like this into the log: @@ -768,7 +816,8 @@ void LaTeX::deplog(DepTable & head) // This line is not present if no toc should be created. static regex miktexTocReg("\\\\tf@toc=\\\\write.*"); - ifstream ifs(logfile.c_str()); + FileName const fn(makeAbsPath(logfile)); + ifstream ifs(fn.toFilesystemEncoding().c_str()); while (ifs) { // Ok, the scanning of files here is not sufficient. // Sometimes files are named by "File: xxx" only @@ -790,6 +839,10 @@ 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)); + if (regex_match(token, sub, reg1)) { static regex reg1_1("\\(([^()]+)"); smatch what; @@ -808,10 +861,15 @@ void LaTeX::deplog(DepTable & head) handleFoundFile(sub.str(1), head); else if (regex_match(token, sub, reg5)) handleFoundFile(sub.str(1), head); + else if (regex_match(token, sub, regnomencl)) + handleFoundFile(sub.str(1), head); else if (regex_match(token, sub, miktexTocReg)) - handleFoundFile(changeExtension(file, ".toc"), head); + handleFoundFile(onlyFilename(changeExtension(file.absFilename(), ".toc")), head); } // Make sure that the main .tex file is in the dependancy file. - head.insert(onlyFilename(file), true); + head.insert(file, true); } + + +} // namespace lyx