diff --git a/src/Buffer.cpp b/src/Buffer.cpp index a6fe5aa932..c82052b00a 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -1300,6 +1300,7 @@ bool Buffer::write(ostream & ofs) const bool Buffer::makeLaTeXFile(FileName const & fname, + string const & original_path, OutputParams const & runparams_in, bool output_preamble, bool output_body) const { @@ -1340,7 +1341,8 @@ bool Buffer::makeLaTeXFile(FileName const & fname, try { os.texrow().reset(); - writeLaTeXSource(os, runparams, output_preamble, output_body); + writeLaTeXSource(os, original_path, + runparams, output_preamble, output_body); } catch (EncodingException & e) { odocstringstream ods; @@ -1383,6 +1385,7 @@ bool Buffer::makeLaTeXFile(FileName const & fname, void Buffer::writeLaTeXSource(otexstream & os, + string const & original_path, OutputParams const & runparams_in, bool const output_preamble, bool const output_body) const { @@ -1409,12 +1412,81 @@ void Buffer::writeLaTeXSource(otexstream & os, } LYXERR(Debug::INFO, "lyx document header finished"); - // With respect to nice LaTeX, usual files have \batchmode + // There are a few differences between nice LaTeX and usual files: + // usual files have \batchmode and special input@path to allow + // inclusion of figures specified by an explicitly relative path + // (i.e., a path starting with './' or '../') with either \input or + // \includegraphics, as the TEXINPUTS method doesn't work in this case. + // input@path is set when the actual parameter original_path is set. + // This is done for usual tex-file, but not for nice-latex-file. + // (Matthias 250696) + // Note that input@path is only needed for something the user does + // in the preamble, included .tex files or ERT, files included by + // LyX work without it. if (output_preamble) { if (!runparams.nice) { // code for usual, NOT nice-latex-file os << "\\batchmode\n"; // changed from \nonstopmode } + if (!original_path.empty()) { + // FIXME UNICODE + // We don't know the encoding of inputpath + docstring const inputpath = from_utf8(original_path); + docstring uncodable_glyphs; + Encoding const * const enc = runparams.encoding; + if (enc) { + for (size_t n = 0; n < inputpath.size(); ++n) { + docstring const glyph = + docstring(1, inputpath[n]); + if (enc->latexChar(inputpath[n], true) != glyph) { + LYXERR0("Uncodable character '" + << glyph + << "' in input path!"); + uncodable_glyphs += glyph; + } + } + } + + // warn user if we found uncodable glyphs. + if (!uncodable_glyphs.empty()) { + frontend::Alert::warning( + _("Uncodable character in file path"), + support::bformat( + _("The path of your document\n" + "(%1$s)\n" + "contains glyphs that are unknown " + "in the current document encoding " + "(namely %2$s). This may result in " + "incomplete output, unless " + "TEXINPUTS contains the document " + "directory and you don't use " + "explicitly relative paths (i.e., " + "paths starting with './' or " + "'../') in the preamble or in ERT." + "\n\nIn case of problems, choose " + "an appropriate document encoding\n" + "(such as utf8) or change the " + "file path name."), + inputpath, uncodable_glyphs)); + } else { + string docdir = + support::latex_path(original_path); + if (contains(docdir, '#')) { + docdir = subst(docdir, "#", "\\#"); + os << "\\catcode`\\#=11" + "\\def\\#{#}\\catcode`\\#=6\n"; + } + if (contains(docdir, '%')) { + docdir = subst(docdir, "%", "\\%"); + os << "\\catcode`\\%=11" + "\\def\\%{%}\\catcode`\\%=14\n"; + } + os << "\\makeatletter\n" + << "\\def\\input@path{{" + << docdir << "/}}\n" + << "\\makeatother\n"; + } + } // get parent macros (if this buffer has a parent) which will be // written at the document begin further down. @@ -1677,6 +1749,7 @@ int Buffer::runChktex() // get LaTeX-Filename FileName const path(temppath()); string const name = addName(path.absFileName(), latexName()); + string const org_path = filePath(); PathChanger p(path); // path to LaTeX file message(_("Running chktex...")); @@ -1686,7 +1759,7 @@ int Buffer::runChktex() runparams.flavor = OutputParams::LATEX; runparams.nice = false; runparams.linelen = lyxrc.plaintext_linelen; - makeLaTeXFile(FileName(name), runparams); + makeLaTeXFile(FileName(name), org_path, runparams); TeXErrors terr; Chktex chktex(lyxrc.chktex_command, onlyFileName(name), filePath()); @@ -3117,7 +3190,7 @@ void Buffer::getSourceCode(odocstream & os, string const format, else { // latex or literate otexstream ots(os, d->texrow); - writeLaTeXSource(ots, runparams, true, true); + writeLaTeXSource(ots, string(), runparams, true, true); } } else { runparams.par_begin = par_begin; @@ -3513,7 +3586,7 @@ bool Buffer::doExport(string const & target, bool put_in_tempdir, // LaTeX backend else if (backend_format == format) { runparams.nice = true; - if (!makeLaTeXFile(FileName(filename), runparams)) { + if (!makeLaTeXFile(FileName(filename), string(), runparams)) { if (d->cloned_buffer_) { d->cloned_buffer_->d->errorLists["Export"] = d->errorLists["Export"]; @@ -3527,7 +3600,7 @@ bool Buffer::doExport(string const & target, bool put_in_tempdir, return false; } else { runparams.nice = false; - if (!makeLaTeXFile(FileName(filename), runparams)) { + if (!makeLaTeXFile(FileName(filename), filePath(), runparams)) { if (d->cloned_buffer_) { d->cloned_buffer_->d->errorLists["Export"] = d->errorLists["Export"]; diff --git a/src/Buffer.h b/src/Buffer.h index 6192dd101a..5c90f51bb6 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -276,6 +276,7 @@ public: /// Just a wrapper for writeLaTeXSource, first creating the ofstream. bool makeLaTeXFile(support::FileName const & filename, + std::string const & original_path, OutputParams const &, bool output_preamble = true, bool output_body = true) const; @@ -302,6 +303,7 @@ public: \endcode */ void writeLaTeXSource(otexstream & os, + std::string const & original_path, OutputParams const &, bool output_preamble = true, bool output_body = true) const; diff --git a/src/BufferList.cpp b/src/BufferList.cpp index 01b344f039..e19c8aa63d 100644 --- a/src/BufferList.cpp +++ b/src/BufferList.cpp @@ -212,7 +212,8 @@ void BufferList::updateIncludedTeXfiles(string const & masterTmpDir, for (; it != end; ++it) { if (!(*it)->isDepClean(masterTmpDir)) { string writefile = addName(masterTmpDir, (*it)->latexName()); - (*it)->makeLaTeXFile(FileName(writefile), runparams, false); + (*it)->makeLaTeXFile(FileName(writefile), masterTmpDir, + runparams, false); (*it)->markDepClean(masterTmpDir); } } diff --git a/src/graphics/PreviewLoader.cpp b/src/graphics/PreviewLoader.cpp index 32b4ec1d86..6b6e1bad71 100644 --- a/src/graphics/PreviewLoader.cpp +++ b/src/graphics/PreviewLoader.cpp @@ -716,7 +716,7 @@ void PreviewLoader::Impl::dumpPreamble(otexstream & os) const runparams.nice = true; runparams.moving_arg = true; runparams.free_spacing = true; - buffer_.writeLaTeXSource(os, runparams, true, false); + buffer_.writeLaTeXSource(os, buffer_.filePath(), runparams, true, false); // FIXME! This is a HACK! The proper fix is to control the 'true' // passed to WriteStream below: diff --git a/src/insets/InsetInclude.cpp b/src/insets/InsetInclude.cpp index 58d46ab094..b3df0d1971 100644 --- a/src/insets/InsetInclude.cpp +++ b/src/insets/InsetInclude.cpp @@ -623,7 +623,8 @@ void InsetInclude::latex(otexstream & os, OutputParams const & runparams) const runparams.master_language = buffer().params().language; runparams.par_begin = 0; runparams.par_end = tmp->paragraphs().size(); - if (!tmp->makeLaTeXFile(tmpwritefile, runparams, false)) { + if (!tmp->makeLaTeXFile(tmpwritefile, masterFileName(buffer()). + onlyPath().absFileName(), runparams, false)) { docstring msg = bformat(_("Included file `%1$s' " "was not exported correctly.\nWarning: " "LaTeX export is probably incomplete."), @@ -662,8 +663,8 @@ void InsetInclude::latex(otexstream & os, OutputParams const & runparams) const // In this case, it's not a LyX file, so we copy the file // to the temp dir, so that .aux files etc. are not created // in the original dir. Files included by this file will be - // found via the environment variable TEXINPUTS, which may be - // set in preferences and by default includes the original dir. + // found via either the environment variable TEXINPUTS, or + // input@path, see ../Buffer.cpp. unsigned long const checksum_in = included_file.checksum(); unsigned long const checksum_out = writefile.checksum(); diff --git a/src/support/docstream.cpp b/src/support/docstream.cpp index a63023ebed..8f3e62d94e 100644 --- a/src/support/docstream.cpp +++ b/src/support/docstream.cpp @@ -510,6 +510,13 @@ otexstream & operator<<(otexstream & ots, docstring const & s) } +otexstream & operator<<(otexstream & ots, string const & s) +{ + ots << s.c_str(); + return ots; +} + + otexstream & operator<<(otexstream & ots, char const * s) { size_t const len = strlen(s); diff --git a/src/support/docstream.h b/src/support/docstream.h index f59030f923..b7e30409b3 100644 --- a/src/support/docstream.h +++ b/src/support/docstream.h @@ -154,6 +154,8 @@ otexstream & operator<<(otexstream &, odocstream_manip); /// otexstream & operator<<(otexstream &, docstring const &); /// +otexstream & operator<<(otexstream &, std::string const &); +/// otexstream & operator<<(otexstream &, char const *); /// otexstream & operator<<(otexstream &, char);