authorlist.record(Author(from_utf8(lyxrc.user_name),
from_utf8(lyxrc.user_email),
from_utf8(lyxrc.user_initials)));
+ // set comparison author
+ authorlist.record(Author(from_utf8("Document Comparison"),
+ docstring(), docstring()));
}
origin.replace(0, sysdirprefix.length() - 1,
package().system_support().absFileName());
}
+ } else if (token == "\\begin_metadata") {
+ readDocumentMetadata(lex);
} else if (token == "\\begin_preamble") {
readPreamble(lex);
} else if (token == "\\begin_local_layout") {
baseClass()->name()), "layout"))
<< '\n';
+ // then document metadata
+ if (!document_metadata.empty()) {
+ // remove '\n' from the end of document_metadata
+ docstring const tmpmd = rtrim(document_metadata, "\n");
+ os << "\\begin_metadata\n"
+ << to_utf8(tmpmd)
+ << "\n\\end_metadata\n";
+ }
+
// then the preamble
if (!preamble.empty()) {
// remove '\n' from the end of preamble
bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
FileName const & filepath) const
{
+ // DocumentMetadata must come before anything else
+ if (features.isAvailableAtLeastFrom("LaTeX", 2022, 6)
+ && !containsOnly(document_metadata, " \n\t")) {
+ // Check if the user preamble contains uncodable glyphs
+ odocstringstream doc_metadata;
+ docstring uncodable_glyphs;
+ Encoding const * const enc = features.runparams().encoding;
+ if (enc) {
+ for (char_type c : document_metadata) {
+ if (!enc->encodable(c)) {
+ docstring const glyph(1, c);
+ LYXERR0("Uncodable character '"
+ << glyph
+ << "' in document metadata!");
+ uncodable_glyphs += glyph;
+ if (features.runparams().dryrun) {
+ doc_metadata << "<" << _("LyX Warning: ")
+ << _("uncodable character") << " '";
+ doc_metadata.put(c);
+ doc_metadata << "'>";
+ }
+ } else
+ doc_metadata.put(c);
+ }
+ } else
+ doc_metadata << document_metadata;
+
+ // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
+ if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
+ frontend::Alert::warning(
+ _("Uncodable character in document metadata"),
+ support::bformat(
+ _("The metadata 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 "
+ "metadata accordingly."),
+ uncodable_glyphs));
+ }
+ if (!doc_metadata.str().empty()) {
+ os << "\\DocumentMetadata{\n"
+ << doc_metadata.str()
+ << "}\n";
+ }
+ }
+
// http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
// !! To use the Fix-cm package, load it before \documentclass, and use the command
// \RequirePackage to do so, rather than the normal \usepackage
if (useNonTeXFonts) {
// Babel (as of 2017/11/03) loads fontspec itself
+ // However, it does so only if a non-default font is requested via \babelfont
+ // Thus load fontspec if this is not the case and we need fontspec features
+ bool const babel_needfontspec =
+ !features.isAvailableAtLeastFrom("babel", 2017, 11, 3)
+ || (fontsRoman() == "default"
+ && fontsSans() == "default"
+ && fontsTypewriter() == "default"
+ // these need fontspec features
+ && (features.isRequired("textquotesinglep")
+ || features.isRequired("textquotedblp")));
if (!features.isProvided("fontspec")
- && !(features.useBabel() && features.isAvailable("babel-2017/11/03")))
+ && (!features.useBabel() || babel_needfontspec))
os << "\\usepackage{fontspec}\n";
if (features.mustProvide("unicode-math")
&& features.isAvailable("unicode-math"))
if (!features.runparams().includeall && !included_children_.empty()) {
os << "\\includeonly{";
bool first = true;
+ // we do not use "auto const &" here, because incfile is modified later
+ // coverity[auto_causes_copy]
for (auto incfile : included_children_) {
FileName inc = makeAbsPath(incfile, filepath.absFileName());
string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
os << from_utf8(output_sync_macro) +"\n";
else if (features.runparams().flavor == Flavor::LaTeX)
os << "\\usepackage[active]{srcltx}\n";
- else if (features.runparams().flavor == Flavor::PdfLaTeX)
+ else
os << "\\synctex=-1\n";
}
if (!tmppreamble.str.empty())
atlyxpreamble << "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
"LyX specific LaTeX commands.\n"
- << move(tmppreamble)
+ << std::move(tmppreamble)
<< '\n';
}
// the text class specific preamble
}
+void BufferParams::readDocumentMetadata(Lexer & lex)
+{
+ if (lex.getString() != "\\begin_metadata")
+ lyxerr << "Error (BufferParams::readDocumentMetadata):"
+ "consistency check failed." << endl;
+
+ document_metadata = lex.getLongString(from_ascii("\\end_metadata"));
+}
+
+
void BufferParams::readLocalLayout(Lexer & lex, bool forced)
{
string const expected = forced ? "\\begin_forced_local_layout" :
if (useNonTeXFonts)
return;
+ string const doc_encoding = encoding().latexName();
+ Encoding::Package const package = encoding().package();
+ // (dvi)lualatex uses luainputenc rather than inputenc
+ string const inputenc_package =
+ (features.runparams().flavor == Flavor::LuaTeX
+ || features.runparams().flavor == Flavor::DviLuaTeX)
+ ? "luainputenc" : "inputenc";
+
if (inputenc == "auto-legacy") {
- string const doc_encoding =
- language->encoding()->latexName();
- Encoding::Package const package =
- language->encoding()->package();
-
- // Create list of inputenc options:
- set<string> encoding_set;
- // luainputenc fails with more than one encoding
- if (features.runparams().flavor != Flavor::LuaTeX
- && features.runparams().flavor != Flavor::DviLuaTeX)
- // list all input encodings used in the document
- encoding_set = features.getEncodingSet(doc_encoding);
-
- // The "japanese" babel-language requires the pLaTeX engine
+ // The "japanese" babel language requires the pLaTeX engine
// which conflicts with "inputenc".
// See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
- if ((!encoding_set.empty() || package == Encoding::inputenc)
- && !features.isRequired("japanese")
+ if (!features.isRequired("japanese")
&& !features.isProvided("inputenc")) {
- os << "\\usepackage[";
- set<string>::const_iterator it = encoding_set.begin();
- set<string>::const_iterator const end = encoding_set.end();
- if (it != end) {
- os << from_ascii(*it);
- ++it;
- }
- for (; it != end; ++it)
- os << ',' << from_ascii(*it);
if (package == Encoding::inputenc) {
- if (!encoding_set.empty())
- os << ',';
- os << from_ascii(doc_encoding);
+ // Main language requires (lua)inputenc
+ os << "\\usepackage[" << doc_encoding << "]{"
+ << inputenc_package << "}\n";
+ } else {
+ // We might have an additional language that requires inputenc
+ set<string> encoding_set = features.getEncodingSet(doc_encoding);
+ bool inputenc = false;
+ for (auto const & enc : encoding_set) {
+ if (encodings.fromLaTeXName(enc)
+ && encodings.fromLaTeXName(enc)->package() == Encoding::inputenc) {
+ inputenc = true;
+ break;
+ }
+ }
+ if (inputenc)
+ // load (lua)inputenc without options
+ // (the encoding is loaded later)
+ os << "\\usepackage{" << inputenc_package << "}\n";
}
- if (features.runparams().flavor == Flavor::LuaTeX
- || features.runparams().flavor == Flavor::DviLuaTeX)
- os << "]{luainputenc}\n";
- else
- os << "]{inputenc}\n";
}
} else if (inputenc != "auto-legacy-plain") {
- switch (encoding().package()) {
+ switch (package) {
case Encoding::none:
case Encoding::CJK:
case Encoding::japanese:
if (encoding().iconvName() != "UTF-8"
- && !features.runparams().isFullUnicode())
- // don't default to [utf8]{inputenc} with TeXLive >= 18
- os << "\\ifdefined\\UseRawInputEncoding\n"
- << " \\UseRawInputEncoding\\fi\n";
+ && !features.runparams().isFullUnicode()
+ && features.isAvailableAtLeastFrom("LaTeX", 2018, 4))
+ // don't default to [utf8]{inputenc} with LaTeX >= 2018/04
+ os << "\\UseRawInputEncoding\n";
break;
case Encoding::inputenc:
// do not load inputenc if japanese is used
if (features.isRequired("japanese")
|| features.isProvided("inputenc"))
break;
- os << "\\usepackage[" << from_ascii(encoding().latexName());
- if (features.runparams().flavor == Flavor::LuaTeX
- || features.runparams().flavor == Flavor::DviLuaTeX)
- os << "]{luainputenc}\n";
- else
- os << "]{inputenc}\n";
+ // The 2022 release of ucs.sty uses the default utf8
+ // inputenc encoding with 'utf8x' inputenc if the ucs
+ // package is not loaded before inputenc.
+ // This breaks existing documents that use utf8x
+ // and also makes utf8x redundant.
+ // Thus we load ucs.sty in order to keep functionality
+ // that would otherwise be silently dropped.
+ if (doc_encoding == "utf8x"
+ && features.isAvailableAtLeastFrom("ucs", 2022, 8, 7)
+ && !features.isProvided("ucs"))
+ os << "\\usepackage{ucs}\n";
+ os << "\\usepackage[" << doc_encoding << "]{"
+ << inputenc_package << "}\n";
break;
}
}
- if (inputenc == "auto-legacy-plain" || features.isRequired("japanese")) {
- // don't default to [utf8]{inputenc} with TeXLive >= 18
- os << "\\ifdefined\\UseRawInputEncoding\n";
- os << " \\UseRawInputEncoding\\fi\n";
- }
+ if ((inputenc == "auto-legacy-plain" || features.isRequired("japanese"))
+ && features.isAvailableAtLeastFrom("LaTeX", 2018, 4))
+ // don't default to [utf8]{inputenc} with LaTeX >= 2018/04
+ os << "\\UseRawInputEncoding\n";
}
// As of 2017/11/03, Babel has its own higher-level
// interface on top of fontspec that is to be used.
bool const babelfonts = features.useBabel()
- && features.isAvailable("babel-2017/11/03");
+ && features.isAvailableAtLeastFrom("babel", 2017, 11, 3);
string const texmapping =
(features.runparams().flavor == Flavor::XeTeX) ?
"Mapping=tex-text" : "Ligatures=TeX";
{
string const & lang = bp.language->lang();
setLanguage(lang);
+ quotes_style = bp.quotes_style;
layout_modules_ = bp.layout_modules_;
string const & doc_class = bp.documentClass().name();
setBaseClass(doc_class);
}
+BufferParams const & defaultBufferParams()
+{
+ static BufferParams default_params;
+ return default_params;
+}
+
} // namespace lyx