#include "support/gettext.h"
#include "support/Messages.h"
#include "support/mutex.h"
+#include "support/Package.h"
#include "support/Translator.h"
#include "support/lstrings.h"
} else if (token == "\\origin") {
lex.eatLine();
origin = lex.getString();
+ string const sysdirprefix = "/systemlyxdir/";
+ if (prefixIs(origin, sysdirprefix)) {
+ origin.replace(0, sysdirprefix.length() - 1,
+ package().system_support().absFileName());
+ }
} else if (token == "\\begin_preamble") {
readPreamble(lex);
} else if (token == "\\begin_local_layout") {
} else if (token == "\\master") {
lex.eatLine();
master = lex.getString();
+ if (!filepath.empty() && FileName::isAbsolute(origin)) {
+ bool const isabs = FileName::isAbsolute(master);
+ FileName const abspath(isabs ? master : origin + master);
+ bool const moved = filepath != FileName(origin);
+ if (moved && abspath.exists()) {
+ docstring const path = isabs
+ ? from_utf8(master)
+ : from_utf8(abspath.realPath());
+ docstring const refpath =
+ from_utf8(filepath.absFileName());
+ master = to_utf8(makeRelPath(path, refpath));
+ }
+ }
} else if (token == "\\suppress_date") {
lex >> suppress_date;
} else if (token == "\\justification") {
}
+namespace {
+ // Quote argument if it contains spaces
+ string quoteIfNeeded(string const & str) {
+ if (contains(str, ' '))
+ return "\"" + str + "\"";
+ return str;
+ }
+}
+
+
void BufferParams::writeFile(ostream & os, Buffer const * buf) const
{
// The top of the file is written by the buffer.
// Prints out the buffer info into the .lyx file given by file
// the document directory
- os << "\\origin " << buf->filePath() << '\n';
+ string filepath = buf->filePath();
+ string const sysdir = package().system_support().absFileName();
+ if (prefixIs(filepath, sysdir))
+ filepath.replace(0, sysdir.length(), "/systemlyxdir/");
+ else if (!lyxrc.save_origin)
+ filepath = "unavailable";
+ os << "\\origin " << quoteIfNeeded(filepath) << '\n';
// the textclass
- os << "\\textclass " << buf->includedFilePath(addName(buf->layoutPos(),
- baseClass()->name()), "layout")
+ os << "\\textclass "
+ << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
+ baseClass()->name()), "layout"))
<< '\n';
// then the preamble
}
// some languages are only available via polyglossia
- if (features.runparams().flavor == OutputParams::XETEX
+ if ((features.runparams().flavor == OutputParams::XETEX
+ || features.runparams().flavor == OutputParams::LUATEX)
&& (features.hasPolyglossiaExclusiveLanguages()
|| useNonTeXFonts))
features.require("polyglossia");
atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
/* the user-defined preamble */
- if (!containsOnly(preamble, " \n\t"))
+ if (!containsOnly(preamble, " \n\t")) {
// FIXME UNICODE
atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
- "User specified LaTeX commands.\n"
- + from_utf8(preamble) + '\n';
+ "User specified LaTeX commands.\n";
+
+ // Check if the user preamble contains uncodable glyphs
+ docstring const u_preamble = from_utf8(preamble);
+ odocstringstream user_preamble;
+ docstring uncodable_glyphs;
+ Encoding const * const enc = features.runparams().encoding;
+ if (enc) {
+ for (size_t n = 0; n < u_preamble.size(); ++n) {
+ char_type c = u_preamble[n];
+ if (!enc->encodable(c)) {
+ docstring const glyph(1, c);
+ LYXERR0("Uncodable character '"
+ << glyph
+ << "' in user preamble!");
+ uncodable_glyphs += glyph;
+ if (features.runparams().dryrun) {
+ user_preamble << "<" << _("LyX Warning: ")
+ << _("uncodable character") << " '";
+ user_preamble.put(c);
+ user_preamble << "'>";
+ }
+ } else
+ user_preamble.put(c);
+ }
+ } else
+ user_preamble << u_preamble;
+
+ // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
+ if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
+ frontend::Alert::warning(
+ _("Uncodable character in user preamble"),
+ support::bformat(
+ _("The user preamble of your document contains glyphs "
+ "that are unknown in the current document encoding "
+ "(namely %1$s).\nThese glyphs are omitted "
+ " from the output, which may result in "
+ "incomplete output."
+ "\n\nPlease select an appropriate "
+ "document encoding\n"
+ "(such as utf8) or change the "
+ "preamble code accordingly."),
+ uncodable_glyphs));
+ }
+ atlyxpreamble += user_preamble.str() + '\n';
+ }
// footmisc must be loaded after setspace
// Load it here to avoid clashes with footmisc loaded in the user
string format = documentClass().outputFormat();
if (format == "latex") {
if (useNonTeXFonts)
- return "xetex";
+ return "xetex"; // FIXME: why not "luatex"?
if (encoding().package() == Encoding::japanese)
return "platex";
}
else if (dformat == "lyx")
result = OutputParams::LYX;
else if (dformat == "pdflatex")
- result = OutputParams::PDFLATEX;
+ result = OutputParams::PDFLATEX;
else if (dformat == "xetex")
result = OutputParams::XETEX;
else if (dformat == "luatex")
void BufferParams::writeEncodingPreamble(otexstream & os,
LaTeXFeatures & features) const
{
- // XeTeX does not need this
- if (features.runparams().flavor == OutputParams::XETEX)
+ // "inputenc" package not required with non-TeX fonts.
+ if (useNonTeXFonts)
return;
- // LuaTeX neither, but with tex fonts, we need to load
- // the luainputenc package.
- if (features.runparams().flavor == OutputParams::LUATEX
- || features.runparams().flavor == OutputParams::DVILUATEX) {
- if (!useNonTeXFonts && inputenc != "default"
- && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
- || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
- os << "\\usepackage[utf8]{luainputenc}\n";
- }
+ // "inputenc" fails with XeTeX (even in 8-bit compatiblitly mode) and with TeX fonts,
+ // (this is a bug in the "inputenc" package see #9740).
+ if (features.runparams().flavor == OutputParams::XETEX)
return;
- }
+ // For LuaTeX with TeX fonts, we can load
+ // the "luainputenc" package with the specified encoding(s) (see below).
+
if (inputenc == "auto") {
string const doc_encoding =
language->encoding()->latexName();
os << ',';
os << from_ascii(doc_encoding);
}
- os << "]{inputenc}\n";
+ if (features.runparams().flavor == OutputParams::LUATEX
+ || features.runparams().flavor == OutputParams::DVILUATEX)
+ os << "]{luainputenc}\n";
+ else
+ os << "]{inputenc}\n";
}
if (package == Encoding::CJK || features.mustProvide("CJK")) {
if (language->encoding()->name() == "utf8-cjk"
if (features.isRequired("japanese")
|| features.isProvided("inputenc"))
break;
- os << "\\usepackage[" << from_ascii(encoding().latexName())
- << "]{inputenc}\n";
+ os << "\\usepackage[" << from_ascii(encoding().latexName());
+ if (features.runparams().flavor == OutputParams::LUATEX
+ || features.runparams().flavor == OutputParams::DVILUATEX)
+ os << "]{luainputenc}\n";
+ else
+ os << "]{inputenc}\n";
break;
case Encoding::CJK:
if (encoding().name() == "utf8-cjk"
Encoding const & BufferParams::encoding() const
{
- // FIXME: actually, we should check for the flavor
- // or runparams.isFullyUnicode() here:
- // This check will not work with XeTeX/LuaTeX and tex fonts.
- // Thus we have to reset the encoding in Buffer::makeLaTeXFile
+ // FIXME: additionally, we must check for runparams().flavor == XeTeX
+ // or runparams.isFullUnicode() to care for the combination
+ // of XeTeX and TeX-fonts (see #9740).
+ // Currently, we reset the encoding in Buffer::makeLaTeXFile
// (for export) and Buffer::writeLaTeXSource (for preview).
if (useNonTeXFonts)
return *(encodings.fromLyXName("utf8-plain"));