X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferParams.cpp;h=e1a279f3e1761dada9c7a8b8c33fd5ae3b179efc;hb=ed44aed58cd48eb744cb50a546859297f9e67e58;hp=e96067a9859db60e6aa215048296284677ee2905;hpb=ecbd047cffa1c4af95cf4ab91a7d2fded4a5584c;p=lyx.git diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp index e96067a985..e1a279f3e1 100644 --- a/src/BufferParams.cpp +++ b/src/BufferParams.cpp @@ -28,11 +28,11 @@ #include "ColorSet.h" #include "Converter.h" #include "Encoding.h" -#include "HSpace.h" #include "IndicesList.h" #include "Language.h" #include "LaTeXFeatures.h" #include "LaTeXFonts.h" +#include "Length.h" #include "ModuleList.h" #include "Font.h" #include "Lexer.h" @@ -102,7 +102,6 @@ static char const * const tex_graphics[] = { }; - namespace lyx { // Local translators @@ -308,7 +307,7 @@ bool inSystemDir(FileName const & document_dir, string & system_dir) string dir = document_dir.absFileName(); - for (int i = 0; i < 2; ++i) { + for (int i = 0; i < 3; ++i) { dir = addPath(dir, ".."); if (!fileSearch(dir, "configure.py").empty() && !fileSearch(dir, "chkconfig.ltx").empty()) { @@ -323,7 +322,7 @@ bool inSystemDir(FileName const & document_dir, string & system_dir) return false; } -} // anon namespace +} // namespace class BufferParams::Impl @@ -337,10 +336,11 @@ public: Bullet user_defined_bullets[4]; IndicesList indiceslist; Spacing spacing; + Length parindent; + Length mathindent; /** This is the amount of space used for paragraph_separation "skip", * and for detached paragraphs in "indented" documents. */ - HSpace indentation; VSpace defskip; PDFOptions pdfoptions; LayoutFileIndex baseClass_; @@ -379,10 +379,12 @@ BufferParams::BufferParams() : pimpl_(new Impl) { setBaseClass(defaultBaseclass()); - cite_engine_.push_back("basic"); + cite_engine_ = "basic"; cite_engine_type_ = ENGINE_TYPE_DEFAULT; makeDocumentClass(); paragraph_separation = ParagraphIndentSeparation; + is_math_indent = false; + math_numbering_side = DEFAULT; quotes_style = InsetQuotesParams::EnglishQuotes; dynamic_quotes = false; fontsize = "default"; @@ -391,8 +393,9 @@ BufferParams::BufferParams() papersize = PAPER_DEFAULT; orientation = ORIENTATION_PORTRAIT; use_geometry = false; - biblio_style = "plain"; + biblio_style = string(); use_bibtopic = false; + multibib = string(); use_indices = false; save_transient_properties = true; track_changes = false; @@ -402,7 +405,7 @@ BufferParams::BufferParams() secnumdepth = 3; tocdepth = 3; language = default_language; - fontenc = "global"; + fontenc = "auto"; fonts_roman[0] = "default"; fonts_roman[1] = "default"; fonts_sans[0] = "default"; @@ -414,13 +417,16 @@ BufferParams::BufferParams() fonts_default_family = "default"; useNonTeXFonts = false; use_microtype = false; + use_dash_ligatures = true; fonts_expert_sc = false; - fonts_old_figures = false; + fonts_roman_osf = false; + fonts_sans_osf = false; + fonts_typewriter_osf = false; fonts_sans_scale[0] = 100; fonts_sans_scale[1] = 100; fonts_typewriter_scale[0] = 100; fonts_typewriter_scale[1] = 100; - inputenc = "auto"; + inputenc = "utf8"; lang_package = "default"; graphics_driver = "default"; default_output_format = "default"; @@ -430,6 +436,7 @@ BufferParams::BufferParams() columns = 1; listings_params = string(); pagestyle = "default"; + tablestyle = "default"; suppress_date = false; justification = true; // no color is the default (white) @@ -454,8 +461,11 @@ BufferParams::BufferParams() html_css_as_file = false; display_pixel_ratio = 1.0; + shell_escape = false; output_sync = false; use_refstyle = true; + use_minted = false; + use_lineno = false; // map current author author_map_[pimpl_->authorlist.get(0).bufferId()] = 0; @@ -522,6 +532,14 @@ map const & BufferParams::auto_packages() } +bool BufferParams::useBibtopic() const +{ + if (useBiblatex()) + return false; + return (use_bibtopic || (!multibib.empty() && multibib != "child")); +} + + AuthorList & BufferParams::authors() { return pimpl_->authorlist; @@ -616,15 +634,27 @@ PDFOptions const & BufferParams::pdfoptions() const } -HSpace const & BufferParams::getIndentation() const +Length const & BufferParams::getMathIndent() const +{ + return pimpl_->mathindent; +} + + +void BufferParams::setMathIndent(Length const & indent) { - return pimpl_->indentation; + pimpl_->mathindent = indent; } -void BufferParams::setIndentation(HSpace const & indent) +Length const & BufferParams::getParIndent() const { - pimpl_->indentation = indent; + return pimpl_->parindent; +} + + +void BufferParams::setParIndent(Length const & indent) +{ + pimpl_->parindent = indent; } @@ -642,6 +672,19 @@ void BufferParams::setDefSkip(VSpace const & vs) } +BufferParams::MathNumber BufferParams::getMathNumber() const +{ + if (math_numbering_side != DEFAULT) + return math_numbering_side; + // FIXME: do not hardcode language here + else if (language->lang() == "arabic_arabi" + || documentClass().provides("leqno")) + return LEFT; + else + return RIGHT; +} + + string BufferParams::readToken(Lexer & lex, string const & token, FileName const & filepath) { @@ -791,26 +834,41 @@ string BufferParams::readToken(Lexer & lex, string const & token, lex >> useNonTeXFonts; } else if (token == "\\font_sc") { lex >> fonts_expert_sc; - } else if (token == "\\font_osf") { - lex >> fonts_old_figures; + } else if (token == "\\font_roman_osf") { + lex >> fonts_roman_osf; + } else if (token == "\\font_sans_osf") { + lex >> fonts_sans_osf; + } else if (token == "\\font_typewriter_osf") { + lex >> fonts_typewriter_osf; + } else if (token == "\\font_roman_opts") { + lex >> font_roman_opts; } else if (token == "\\font_sf_scale") { lex >> fonts_sans_scale[0]; lex >> fonts_sans_scale[1]; + } else if (token == "\\font_sans_opts") { + lex >> font_sans_opts; } else if (token == "\\font_tt_scale") { lex >> fonts_typewriter_scale[0]; lex >> fonts_typewriter_scale[1]; + } else if (token == "\\font_typewriter_opts") { + lex >> font_typewriter_opts; } else if (token == "\\font_cjk") { lex >> fonts_cjk; } else if (token == "\\use_microtype") { lex >> use_microtype; + } else if (token == "\\use_dash_ligatures") { + lex >> use_dash_ligatures; } else if (token == "\\paragraph_separation") { string parsep; lex >> parsep; paragraph_separation = parseptranslator().find(parsep); } else if (token == "\\paragraph_indentation") { lex.next(); - string indentation = lex.getString(); - pimpl_->indentation = HSpace(indentation); + string parindent = lex.getString(); + if (parindent == "default") + pimpl_->parindent = Length(); + else + pimpl_->parindent = Length(parindent); } else if (token == "\\defskip") { lex.next(); string const defskip = lex.getString(); @@ -818,6 +876,24 @@ string BufferParams::readToken(Lexer & lex, string const & token, if (pimpl_->defskip.kind() == VSpace::DEFSKIP) // that is invalid pimpl_->defskip = VSpace(VSpace::MEDSKIP); + } else if (token == "\\is_math_indent") { + lex >> is_math_indent; + } else if (token == "\\math_indentation") { + lex.next(); + string mathindent = lex.getString(); + if (mathindent == "default") + pimpl_->mathindent = Length(); + else + pimpl_->mathindent = Length(mathindent); + } else if (token == "\\math_numbering_side") { + string tmp; + lex >> tmp; + if (tmp == "left") + math_numbering_side = LEFT; + else if (tmp == "right") + math_numbering_side = RIGHT; + else + math_numbering_side = DEFAULT; } else if (token == "\\quotes_style") { string qstyle; lex >> qstyle; @@ -838,8 +914,7 @@ string BufferParams::readToken(Lexer & lex, string const & token, use_package(package, packagetranslator().find(use)); } else if (token == "\\cite_engine") { lex.eatLine(); - vector engine = getVectorFromString(lex.getString()); - setCiteEngine(engine); + cite_engine_ = lex.getString(); } else if (token == "\\cite_engine_type") { string engine_type; lex >> engine_type; @@ -847,8 +922,19 @@ string BufferParams::readToken(Lexer & lex, string const & token, } else if (token == "\\biblio_style") { lex.eatLine(); biblio_style = lex.getString(); + } else if (token == "\\biblio_options") { + lex.eatLine(); + biblio_opts = trim(lex.getString()); + } else if (token == "\\biblatex_bibstyle") { + lex.eatLine(); + biblatex_bibstyle = trim(lex.getString()); + } else if (token == "\\biblatex_citestyle") { + lex.eatLine(); + biblatex_citestyle = trim(lex.getString()); } else if (token == "\\use_bibtopic") { lex >> use_bibtopic; + } else if (token == "\\multibib") { + lex >> multibib; } else if (token == "\\use_indices") { lex >> use_indices; } else if (token == "\\tracking_changes") { @@ -979,6 +1065,8 @@ string BufferParams::readToken(Lexer & lex, string const & token, sides = sidestranslator().find(psides); } else if (token == "\\paperpagestyle") { lex >> pagestyle; + } else if (token == "\\tablestyle") { + lex >> tablestyle; } else if (token == "\\bullet") { readBullets(lex); } else if (token == "\\bulletLaTeX") { @@ -997,6 +1085,8 @@ string BufferParams::readToken(Lexer & lex, string const & token, spacing().set(spacetranslator().find(nspacing), tmp_val); } else if (token == "\\float_placement") { lex >> float_placement; + } else if (token == "\\float_alignment") { + lex >> float_alignment; } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") { string toktmp = pdfoptions().readToken(lex, token); @@ -1027,6 +1117,13 @@ string BufferParams::readToken(Lexer & lex, string const & token, lex >> output_sync_macro; } else if (token == "\\use_refstyle") { lex >> use_refstyle; + } else if (token == "\\use_minted") { + lex >> use_minted; + } else if (token == "\\use_lineno") { + lex >> use_lineno; + } else if (token == "\\lineno_options") { + lex.eatLine(); + lineno_opts = trim(lex.getString()); } else { lyxerr << "BufferParams::readToken(): Unknown token: " << token << endl; @@ -1044,7 +1141,7 @@ namespace { return "\"" + str + "\""; return str; } -} +} // namespace void BufferParams::writeFile(ostream & os, Buffer const * buf) const @@ -1166,16 +1263,24 @@ void BufferParams::writeFile(ostream & os, Buffer const * buf) const << "\n\\font_default_family " << fonts_default_family << "\n\\use_non_tex_fonts " << convert(useNonTeXFonts) << "\n\\font_sc " << convert(fonts_expert_sc) - << "\n\\font_osf " << convert(fonts_old_figures) - << "\n\\font_sf_scale " << fonts_sans_scale[0] - << ' ' << fonts_sans_scale[1] - << "\n\\font_tt_scale " << fonts_typewriter_scale[0] - << ' ' << fonts_typewriter_scale[1] - << '\n'; - if (!fonts_cjk.empty()) { + << "\n\\font_roman_osf " << convert(fonts_roman_osf) + << "\n\\font_sans_osf " << convert(fonts_sans_osf) + << "\n\\font_typewriter_osf " << convert(fonts_typewriter_osf); + if (!font_roman_opts.empty()) + os << "\n\\font_roman_opts \"" << font_roman_opts << "\""; + os << "\n\\font_sf_scale " << fonts_sans_scale[0] + << ' ' << fonts_sans_scale[1]; + if (!font_sans_opts.empty()) + os << "\n\\font_sans_opts \"" << font_sans_opts << "\""; + os << "\n\\font_tt_scale " << fonts_typewriter_scale[0] + << ' ' << fonts_typewriter_scale[1]; + if (!font_typewriter_opts.empty()) + os << "\n\\font_typewriter_opts \"" << font_typewriter_opts << "\""; + os << '\n'; + if (!fonts_cjk.empty()) os << "\\font_cjk " << fonts_cjk << '\n'; - } os << "\\use_microtype " << convert(use_microtype) << '\n'; + os << "\\use_dash_ligatures " << convert(use_dash_ligatures) << '\n'; os << "\\graphics " << graphics_driver << '\n'; os << "\\default_output_format " << default_output_format << '\n'; os << "\\output_sync " << output_sync << '\n'; @@ -1184,9 +1289,10 @@ void BufferParams::writeFile(ostream & os, Buffer const * buf) const os << "\\bibtex_command " << bibtex_command << '\n'; os << "\\index_command " << index_command << '\n'; - if (!float_placement.empty()) { + if (!float_placement.empty()) os << "\\float_placement " << float_placement << '\n'; - } + if (!float_alignment.empty()) + os << "\\float_alignment " << float_alignment << '\n'; os << "\\paperfontsize " << fontsize << '\n'; spacing().writeFile(os); @@ -1202,27 +1308,37 @@ void BufferParams::writeFile(ostream & os, Buffer const * buf) const os << "\n\\cite_engine "; - if (!cite_engine_.empty()) { - LayoutModuleList::const_iterator be = cite_engine_.begin(); - LayoutModuleList::const_iterator en = cite_engine_.end(); - for (LayoutModuleList::const_iterator it = be; it != en; ++it) { - if (it != be) - os << ','; - os << *it; - } - } else { + if (!cite_engine_.empty()) + os << cite_engine_; + else os << "basic"; - } - os << "\n\\cite_engine_type " << theCiteEnginesList.getTypeAsString(cite_engine_type_) - << "\n\\biblio_style " << biblio_style - << "\n\\use_bibtopic " << convert(use_bibtopic) + os << "\n\\cite_engine_type " << theCiteEnginesList.getTypeAsString(cite_engine_type_); + + if (!biblio_style.empty()) + os << "\n\\biblio_style " << biblio_style; + if (!biblio_opts.empty()) + os << "\n\\biblio_options " << biblio_opts; + if (!biblatex_bibstyle.empty()) + os << "\n\\biblatex_bibstyle " << biblatex_bibstyle; + if (!biblatex_citestyle.empty()) + os << "\n\\biblatex_citestyle " << biblatex_citestyle; + if (!multibib.empty()) + os << "\n\\multibib " << multibib; + + os << "\n\\use_bibtopic " << convert(use_bibtopic) << "\n\\use_indices " << convert(use_indices) << "\n\\paperorientation " << string_orientation[orientation] << "\n\\suppress_date " << convert(suppress_date) << "\n\\justification " << convert(justification) << "\n\\use_refstyle " << use_refstyle + << "\n\\use_minted " << use_minted + << "\n\\use_lineno " << use_lineno << '\n'; + + if (!lineno_opts.empty()) + os << "\\lineno_options " << lineno_opts << '\n'; + if (isbackgroundcolor == true) os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n'; if (isfontcolor == true) @@ -1288,15 +1404,32 @@ void BufferParams::writeFile(ostream & os, Buffer const * buf) const << "\n\\paragraph_separation " << string_paragraph_separation[paragraph_separation]; if (!paragraph_separation) - os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand(); + os << "\n\\paragraph_indentation " + << (getParIndent().empty() ? "default" : getParIndent().asString()); else os << "\n\\defskip " << getDefSkip().asLyXCommand(); + os << "\n\\is_math_indent " << is_math_indent; + if (is_math_indent) + os << "\n\\math_indentation " + << (getMathIndent().empty() ? "default" : getMathIndent().asString()); + os << "\n\\math_numbering_side "; + switch(math_numbering_side) { + case LEFT: + os << "left"; + break; + case RIGHT: + os << "right"; + break; + case DEFAULT: + os << "default"; + } os << "\n\\quotes_style " << string_quotes_style[quotes_style] << "\n\\dynamic_quotes " << dynamic_quotes << "\n\\papercolumns " << columns << "\n\\papersides " << sides - << "\n\\paperpagestyle " << pagestyle << '\n'; + << "\n\\paperpagestyle " << pagestyle + << "\n\\tablestyle " << tablestyle << '\n'; if (!listings_params.empty()) os << "\\listings_params \"" << InsetListingsParams(listings_params).encodedString() << "\"\n"; @@ -1449,7 +1582,7 @@ void BufferParams::validate(LaTeXFeatures & features) const if (useNonTeXFonts && fontsMath() != "auto") features.require("unicode-math"); - + if (use_microtype) features.require("microtype"); @@ -1572,6 +1705,21 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, && orientation == ORIENTATION_LANDSCAPE) clsoptions << "landscape,"; + if (is_math_indent) + clsoptions << "fleqn,"; + + switch(math_numbering_side) { + case LEFT: + clsoptions << "leqno,"; + break; + case RIGHT: + clsoptions << "reqno,"; + features.require("amsmath"); + break; + case DEFAULT: + break; + } + // language should be a parameter to \documentclass if (language->babel() == "hebrew" && default_language->babel() != "hebrew") @@ -1582,15 +1730,14 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, bool const use_babel = features.useBabel() && !features.isProvided("babel"); bool const use_polyglossia = features.usePolyglossia(); bool const global = lyxrc.language_global_options; - if (use_babel || (use_polyglossia && global)) { + if (features.useBabel() || (use_polyglossia && global)) { language_options << features.getBabelLanguages(); if (!language->babel().empty()) { if (!language_options.str().empty()) language_options << ','; language_options << language->babel(); } - if (global && !features.needBabelLangOptions() - && !language_options.str().empty()) + if (global && !language_options.str().empty()) clsoptions << language_options.str() << ','; } @@ -1615,7 +1762,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, // if we use fontspec or newtxmath, we have to load the AMS packages here string const ams = features.loadAMSPackages(); - bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1"); + bool const ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1"); bool const use_newtxmath = theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage( ot1, false, false) == "newtxmath"; @@ -1623,16 +1770,29 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, os << from_ascii(ams); if (useNonTeXFonts) { - if (!features.isProvided("fontspec")) + // Babel (as of 2017/11/03) loads fontspec itself + if (!features.isProvided("fontspec") + && !(features.useBabel() && features.isAvailable("babel-2017/11/03"))) os << "\\usepackage{fontspec}\n"; if (features.mustProvide("unicode-math") && features.isAvailable("unicode-math")) os << "\\usepackage{unicode-math}\n"; } + // load CJK support package before font selection + // (see autotests/export/latex/CJK/micro-sign_utf8-cjk-libertine.lyx) + if (!useNonTeXFonts && encoding().package() != Encoding::none && inputenc != "utf8x" + && (encoding().package() == Encoding::CJK || features.mustProvide("CJK"))) { + if (inputenc == "utf8-cjk" || inputenc == "utf8") + os << "\\usepackage{CJKutf8}\n"; + else + os << "\\usepackage[encapsulated]{CJK}\n"; + } + // font selection must be done before loading fontenc.sty + // but after babel with non-TeX fonts string const fonts = loadFonts(features); - if (!fonts.empty()) + if (!fonts.empty() && (!features.useBabel() || !useNonTeXFonts)) os << from_utf8(fonts); if (fonts_default_family != "default") @@ -1640,12 +1800,14 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, << from_ascii(fonts_default_family) << "}\n"; // set font encoding - // XeTeX and LuaTeX (with OS fonts) do not need fontenc + // non-TeX fonts use font encoding TU (set by fontspec) if (!useNonTeXFonts && !features.isProvided("fontenc") - && font_encoding() != "default") { + && main_font_encoding() != "default") { // get main font encodings vector fontencs = font_encodings(); // get font encodings of secondary languages + // FIXME: some languages (hebrew, ...) assume a standard font encoding as last + // option (for text in other languages). features.getFontEncodings(fontencs); if (!fontencs.empty()) { os << "\\usepackage[" @@ -1654,8 +1816,17 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, } } + // Load textcomp and pmboxdraw before (lua)inputenc (#11454) + if (features.mustProvide("textcomp")) + os << "\\usepackage{textcomp}\n"; + if (features.mustProvide("pmboxdraw")) + os << "\\usepackage{pmboxdraw}\n"; + // handle inputenc etc. - writeEncodingPreamble(os, features); + // (In documents containing text in Thai language, + // we must load inputenc after babel, see lib/languages). + if (!contains(features.getBabelPostsettings(), from_ascii("thai.ldf"))) + writeEncodingPreamble(os, features); // includeonly if (!features.runparams().includeall && !included_children_.empty()) { @@ -1889,9 +2060,19 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, } else { // when separation by indentation // only output something when a width is given - if (getIndentation().asLyXCommand() != "default") { + if (!getParIndent().empty()) { os << "\\setlength{\\parindent}{" - << from_utf8(getIndentation().asLatexCommand()) + << from_utf8(getParIndent().asLatexString()) + << "}\n"; + } + } + + if (is_math_indent) { + // when formula indentation + // only output something when it is not the default + if (!getMathIndent().empty()) { + os << "\\setlength{\\mathindent}{" + << from_utf8(getMathIndent().asString()) << "}\n"; } } @@ -1920,18 +2101,17 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html os << from_ascii(features.getColorOptions()); - // If we use hyperref, jurabib, japanese, varioref or vietnamese, + // If we use hyperref, jurabib, japanese or varioref, // we have to call babel before if (use_babel && (features.isRequired("jurabib") || features.isRequired("hyperref") || features.isRequired("varioref") - || features.isRequired("vietnamese") || features.isRequired("japanese"))) { os << features.getBabelPresettings(); // FIXME UNICODE os << from_utf8(babelCall(language_options.str(), - features.needBabelLangOptions())) + '\n'; + !lyxrc.language_global_options)) + '\n'; os << features.getBabelPostsettings(); } @@ -1943,20 +2123,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, IndicesList::const_iterator iit = indiceslist().begin(); IndicesList::const_iterator iend = indiceslist().end(); for (; iit != iend; ++iit) { - pair indexname_latex = - features.runparams().encoding->latexString(iit->index(), - features.runparams().dryrun); - if (!indexname_latex.second.empty()) { - // issue a warning about omitted characters - // FIXME: should be passed to the error dialog - frontend::Alert::warning(_("Uncodable characters"), - bformat(_("The following characters that are used in an index name are not\n" - "representable in the current encoding and therefore have been omitted:\n%1$s."), - indexname_latex.second)); - } - os << "\\newindex["; - os << indexname_latex.first; - os << "]{"; + os << "\\newindex{"; os << escape(iit->shortcut()); os << "}\n"; } @@ -1978,14 +2145,22 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, OutputParams tmp_params = features.runparams(); pdfoptions().writeLaTeX(tmp_params, os, features.isProvided("hyperref")); - // correctly break URLs with hyperref and dvi output - if (features.runparams().flavor == OutputParams::LATEX + // correctly break URLs with hyperref and dvi/ps output + if (features.runparams().hyperref_driver == "dvips" && features.isAvailable("breakurl")) os << "\\usepackage{breakurl}\n"; } else if (features.isRequired("nameref")) // hyperref loads this automatically os << "\\usepackage{nameref}\n"; + if (use_lineno){ + os << "\\usepackage"; + if (!lineno_opts.empty()) + os << "[" << lineno_opts << "]"; + os << "{lineno}\n"; + os << "\\linenumbers\n"; + } + // bibtopic needs to be loaded after hyperref. // the dot provides the aux file naming which LyX can detect. if (features.mustProvide("bibtopic")) @@ -2131,41 +2306,81 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, << "\\makeatother\n\n"; // We try to load babel late, in case it interferes with other packages. - // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be - // called after babel, though. + // Jurabib, hyperref, varioref, bicaption, menukeys and listings (bug 8995) + // have to be called after babel, though. if (use_babel && !features.isRequired("jurabib") && !features.isRequired("hyperref") - && !features.isRequired("varioref") - && !features.isRequired("vietnamese") + && !features.isRequired("varioref") && !features.isRequired("japanese")) { os << features.getBabelPresettings(); // FIXME UNICODE os << from_utf8(babelCall(language_options.str(), - features.needBabelLangOptions())) + '\n'; + !lyxrc.language_global_options)) + '\n'; os << features.getBabelPostsettings(); } + // In documents containing text in Thai language, + // we must load inputenc after babel (see lib/languages). + if (contains(features.getBabelPostsettings(), from_ascii("thai.ldf"))) + writeEncodingPreamble(os, features); + + // font selection must be done after babel with non-TeX fonts + if (!fonts.empty() && features.useBabel() && useNonTeXFonts) + os << from_utf8(fonts); + if (features.isRequired("bicaption")) os << "\\usepackage{bicaption}\n"; - if (!listings_params.empty() || features.mustProvide("listings")) - os << "\\usepackage{listings}\n"; - if (!listings_params.empty()) { - os << "\\lstset{"; + if (!listings_params.empty() + || features.mustProvide("listings") + || features.mustProvide("minted")) { + if (use_minted) + os << "\\usepackage{minted}\n"; + else + os << "\\usepackage{listings}\n"; + } + string lst_params = listings_params; + // If minted, do not output the language option (bug 11203) + if (use_minted && contains(lst_params, "language=")) { + vector opts = + getVectorFromString(lst_params, ",", false); + for (size_t i = 0; i < opts.size(); ++i) { + if (prefixIs(opts[i], "language=")) + opts.erase(opts.begin() + i--); + } + lst_params = getStringFromVector(opts, ","); + } + if (!lst_params.empty()) { + if (use_minted) + os << "\\setminted{"; + else + os << "\\lstset{"; // do not test validity because listings_params is // supposed to be valid string par = - InsetListingsParams(listings_params).separatedParams(true); + InsetListingsParams(lst_params).separatedParams(true); os << from_utf8(par); os << "}\n"; } - // xunicode needs to be loaded at least after amsmath, amssymb, + // xunicode only needs to be loaded if tipa is used + // (the rest is obsoleted by the new TU encoding). + // It needs to be loaded at least after amsmath, amssymb, // esint and the other packages that provide special glyphs - // The package only supports XeTeX currently. - if (features.runparams().flavor == OutputParams::XETEX - && useNonTeXFonts) + if (features.mustProvide("tipa") && useNonTeXFonts + && !features.isProvided("xunicode")) { + // The `xunicode` package officially only supports XeTeX, + // but also works with LuaTeX. We work around its XeTeX test. + if (features.runparams().flavor != OutputParams::XETEX) { + os << "% Pretend to xunicode that we are XeTeX\n" + << "\\def\\XeTeXpicfile{}\n"; + } os << "\\usepackage{xunicode}\n"; + } - // Polyglossia must be loaded last + // covington must be loaded after beamerarticle + if (features.isRequired("covington")) + os << "\\usepackage{covington}\n"; + + // Polyglossia must be loaded last ... if (use_polyglossia) { // call the package os << "\\usepackage{polyglossia}\n"; @@ -2189,6 +2404,64 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, } } + // ... but before biblatex (see #7065) + if ((features.mustProvide("biblatex") + || features.isRequired("biblatex-chicago")) + && !features.isProvided("biblatex-chicago") + && !features.isProvided("biblatex-natbib") + && !features.isProvided("natbib-internal") + && !features.isProvided("natbib") + && !features.isProvided("jurabib")) { + // The biblatex-chicago package has a differing interface + // it uses a wrapper package and loads styles via fixed options + bool const chicago = features.isRequired("biblatex-chicago"); + string delim = ""; + string opts; + os << "\\usepackage"; + if (!biblatex_bibstyle.empty() + && (biblatex_bibstyle == biblatex_citestyle) + && !chicago) { + opts = "style=" + biblatex_bibstyle; + delim = ","; + } else if (!chicago) { + if (!biblatex_bibstyle.empty()) { + opts = "bibstyle=" + biblatex_bibstyle; + delim = ","; + } + if (!biblatex_citestyle.empty()) { + opts += delim + "citestyle=" + biblatex_citestyle; + delim = ","; + } + } + if (!multibib.empty() && multibib != "child") { + opts += delim + "refsection=" + multibib; + delim = ","; + } + if (bibtexCommand() == "bibtex8" + || prefixIs(bibtexCommand(), "bibtex8 ")) { + opts += delim + "backend=bibtex8"; + delim = ","; + } else if (bibtexCommand() == "bibtex" + || prefixIs(bibtexCommand(), "bibtex ")) { + opts += delim + "backend=bibtex"; + delim = ","; + } + if (!bib_encoding.empty() && encodings.fromLyXName(bib_encoding)) { + opts += delim + "bibencoding=" + + encodings.fromLyXName(bib_encoding)->latexName(); + delim = ","; + } + if (!biblio_opts.empty()) + opts += delim + biblio_opts; + if (!opts.empty()) + os << "[" << opts << "]"; + if (chicago) + os << "{biblatex-chicago}\n"; + else + os << "{biblatex}\n"; + } + + // Load custom language package here if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) { if (lang_package == "default") @@ -2198,8 +2471,14 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, os << '\n'; } + // Since menukeys uses catoptions, which does some heavy changes on key-value options, + // it is recommended to load menukeys as the last package (even after hyperref) + if (features.isRequired("menukeys")) + os << "\\usepackage{menukeys}\n"; + docstring const i18npreamble = - features.getTClassI18nPreamble(use_babel, use_polyglossia); + features.getTClassI18nPreamble(use_babel, use_polyglossia, + use_minted); if (!i18npreamble.empty()) os << i18npreamble + '\n'; @@ -2214,6 +2493,7 @@ void BufferParams::useClassDefaults() sides = tclass.sides(); columns = tclass.columns(); pagestyle = tclass.pagestyle(); + tablestyle = tclass.tablestyle(); use_default_options = true; // Only if class has a ToC hierarchy if (tclass.hasTocLevels()) { @@ -2230,6 +2510,7 @@ bool BufferParams::hasClassDefaults() const return sides == tclass.sides() && columns == tclass.columns() && pagestyle == tclass.pagestyle() + && tablestyle == tclass.tablestyle() && use_default_options && secnumdepth == tclass.secnumdepth() && tocdepth == tclass.tocdepth(); @@ -2256,7 +2537,7 @@ void BufferParams::setDocumentClass(DocumentClassConstPtr tc) } -bool BufferParams::setBaseClass(string const & classname) +bool BufferParams::setBaseClass(string const & classname, string const & path) { LYXERR(Debug::TCLASS, "setBaseClass: " << classname); LayoutFileList & bcl = LayoutFileList::get(); @@ -2272,7 +2553,7 @@ bool BufferParams::setBaseClass(string const & classname) bcl.addEmptyClass(classname); } - bool const success = bcl[classname].load(); + bool const success = bcl[classname].load(path); if (!success) { docstring s = bformat(_("Due to some error in it, the layout file:\n" @@ -2313,18 +2594,12 @@ void BufferParams::makeDocumentClass(bool const clone) invalidateConverterCache(); LayoutModuleList mods; - LayoutModuleList ces; LayoutModuleList::iterator it = layout_modules_.begin(); LayoutModuleList::iterator en = layout_modules_.end(); for (; it != en; ++it) mods.push_back(*it); - it = cite_engine_.begin(); - en = cite_engine_.end(); - for (; it != en; ++it) - ces.push_back(*it); - - doc_class_ = getDocumentClass(*baseClass(), mods, ces, clone); + doc_class_ = getDocumentClass(*baseClass(), mods, cite_engine_, clone); TextClass::ReturnValues success = TextClass::OK; if (!forced_local_layout_.empty()) @@ -2346,12 +2621,6 @@ bool BufferParams::layoutModuleCanBeAdded(string const & modName) const } -bool BufferParams::citationModuleCanBeAdded(string const & modName) const -{ - return cite_engine_.moduleCanBeAdded(modName, baseClass()); -} - - docstring BufferParams::getLocalLayout(bool forced) const { if (forced) @@ -2405,7 +2674,7 @@ FormatList const & BufferParams::exportableFormats(bool only_viewable) const { FormatList & cached = only_viewable ? pimpl_->viewableFormatList : pimpl_->exportableFormatList; - bool & valid = only_viewable ? + bool & valid = only_viewable ? pimpl_->isViewCacheValid : pimpl_->isExportCacheValid; if (valid) return cached; @@ -2415,13 +2684,15 @@ FormatList const & BufferParams::exportableFormats(bool only_viewable) const if (useNonTeXFonts) { excludes.insert("latex"); excludes.insert("pdflatex"); - } - FormatList result = - theConverters().getReachable(backs[0], only_viewable, true, excludes); + } else if (inputenc != "ascii" && inputenc != "utf8-plain") + // XeTeX with TeX fonts requires input encoding ascii (#10600). + excludes.insert("xetex"); + FormatList result = theConverters().getReachable(backs[0], only_viewable, + true, excludes); for (vector::const_iterator it = backs.begin() + 1; it != backs.end(); ++it) { - FormatList r = theConverters().getReachable(*it, only_viewable, - false, excludes); + FormatList r = theConverters().getReachable(*it, only_viewable, + false, excludes); result.insert(result.end(), r.begin(), r.end()); } sort(result.begin(), result.end(), Format::formatSorter); @@ -2445,12 +2716,22 @@ vector BufferParams::backends() const v.push_back("pdflatex"); v.push_back("latex"); } - v.push_back("xetex"); + if (useNonTeXFonts + || inputenc == "ascii" || inputenc == "utf8-plain") + v.push_back("xetex"); v.push_back("luatex"); v.push_back("dviluatex"); } - } else - v.push_back(buffmt); + } else { + string rbuffmt = buffmt; + // If we use an OutputFormat in Japanese docs, + // we need special format in order to get the path + // via pLaTeX (#8823) + if (documentClass().hasOutputFormat() + && encoding().package() == Encoding::japanese) + rbuffmt += "-ja"; + v.push_back(rbuffmt); + } v.push_back("xhtml"); v.push_back("text"); @@ -2493,9 +2774,8 @@ OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const if (find(backs.begin(), backs.end(), dformat) == backs.end()) { // Get shortest path to format Graph::EdgePath path; - for (vector::const_iterator it = backs.begin(); - it != backs.end(); ++it) { - Graph::EdgePath p = theConverters().getPath(*it, dformat); + for (auto const & bvar : backs) { + Graph::EdgePath p = theConverters().getPath(bvar, dformat); if (!p.empty() && (path.empty() || p.size() < path.size())) { path = p; } @@ -2515,14 +2795,15 @@ string BufferParams::getDefaultOutputFormat() const if (!default_output_format.empty() && default_output_format != "default") return default_output_format; - if (isDocBook() - || encoding().package() == Encoding::japanese) { + if (isDocBook()) { FormatList const & formats = exportableFormats(true); if (formats.empty()) return string(); // return the first we find return formats.front()->name(); } + if (encoding().package() == Encoding::japanese) + return lyxrc.default_platex_view_format; if (useNonTeXFonts) return lyxrc.default_otf_view_format; return lyxrc.default_view_format; @@ -2927,28 +3208,34 @@ string const BufferParams::dvips_options() const } -string const BufferParams::font_encoding() const +string const BufferParams::main_font_encoding() const { - return font_encodings().empty() ? "default" : font_encodings().back(); + if (font_encodings().empty()) { + if (ascii_lowercase(language->fontenc(*this)) == "none") + return "none"; + return "default"; + } + return font_encodings().back(); } vector const BufferParams::font_encodings() const { - string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc; + string doc_fontenc = (fontenc == "auto") ? string() : fontenc; vector fontencs; // "default" means "no explicit font encoding" if (doc_fontenc != "default") { - fontencs = getVectorFromString(doc_fontenc); - if (!language->fontenc().empty() - && ascii_lowercase(language->fontenc()) != "none") { - vector fencs = getVectorFromString(language->fontenc()); - vector::const_iterator fit = fencs.begin(); - for (; fit != fencs.end(); ++fit) { - if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end()) - fontencs.push_back(*fit); + if (!doc_fontenc.empty()) + // If we have a custom setting, we use only that! + return getVectorFromString(doc_fontenc); + if (!language->fontenc(*this).empty() + && ascii_lowercase(language->fontenc(*this)) != "none") { + vector fencs = getVectorFromString(language->fontenc(*this)); + for (auto & fe : fencs) { + if (find(fontencs.begin(), fontencs.end(), fe) == fontencs.end()) + fontencs.push_back(fe); } } } @@ -2964,8 +3251,7 @@ string BufferParams::babelCall(string const & lang_opts, bool const langoptions) // other languages are used (lang_opts is then empty) if (lang_opts.empty()) return string(); - // either a specific language (AsBabelOptions setting in - // lib/languages) or the prefs require the languages to + // The prefs may require the languages to // be submitted to babel itself (not the class). if (langoptions) return "\\usepackage[" + lang_opts + "]{babel}"; @@ -2994,36 +3280,33 @@ docstring BufferParams::getGraphicsDriver(string const & package) const void BufferParams::writeEncodingPreamble(otexstream & os, LaTeXFeatures & features) const { - // XeTeX/LuaTeX: (see also #9740) - // With Unicode fonts we use utf8-plain without encoding package. - // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails. - // XeTeX must use ASCII encoding (see Buffer.cpp), - // for LuaTeX, we load "luainputenc" (see below). - if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX) + // With no-TeX fonts we use utf8-plain without encoding package. + if (useNonTeXFonts) return; - if (inputenc == "auto") { + if (inputenc == "auto-legacy") { string const doc_encoding = language->encoding()->latexName(); Encoding::Package const package = language->encoding()->package(); // Create list of inputenc options: - set encodings; + set encoding_set; // luainputenc fails with more than one encoding - if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts + if (features.runparams().flavor != OutputParams::LUATEX + && features.runparams().flavor != OutputParams::DVILUATEX) // list all input encodings used in the document - encodings = features.getEncodingSet(doc_encoding); + encoding_set = features.getEncodingSet(doc_encoding); - // If the "japanese" package (i.e. pLaTeX) is used, - // inputenc must be omitted. - // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html - if ((!encodings.empty() || package == Encoding::inputenc) + // 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") && !features.isProvided("inputenc")) { os << "\\usepackage["; - set::const_iterator it = encodings.begin(); - set::const_iterator const end = encodings.end(); + set::const_iterator it = encoding_set.begin(); + set::const_iterator const end = encoding_set.end(); if (it != end) { os << from_ascii(*it); ++it; @@ -3031,7 +3314,7 @@ void BufferParams::writeEncodingPreamble(otexstream & os, for (; it != end; ++it) os << ',' << from_ascii(*it); if (package == Encoding::inputenc) { - if (!encodings.empty()) + if (!encoding_set.empty()) os << ','; os << from_ascii(doc_encoding); } @@ -3041,17 +3324,16 @@ void BufferParams::writeEncodingPreamble(otexstream & os, else os << "]{inputenc}\n"; } - if (package == Encoding::CJK || features.mustProvide("CJK")) { - if (language->encoding()->name() == "utf8-cjk" - && LaTeXFeatures::isAvailable("CJKutf8")) - os << "\\usepackage{CJKutf8}\n"; - else - os << "\\usepackage{CJK}\n"; - } - } else if (inputenc != "default") { + } else if (inputenc != "auto-legacy-plain") { switch (encoding().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"; break; case Encoding::inputenc: // do not load inputenc if japanese is used @@ -3066,24 +3348,13 @@ void BufferParams::writeEncodingPreamble(otexstream & os, else os << "]{inputenc}\n"; break; - case Encoding::CJK: - if (encoding().name() == "utf8-cjk" - && LaTeXFeatures::isAvailable("CJKutf8")) - os << "\\usepackage{CJKutf8}\n"; - else - os << "\\usepackage{CJK}\n"; - break; - } - // Load the CJK package if needed by a secondary language. - // If the main encoding is some variant of UTF8, use CJKutf8. - if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) { - if (encoding().iconvName() == "UTF-8" - && LaTeXFeatures::isAvailable("CJKutf8")) - os << "\\usepackage{CJKutf8}\n"; - else - os << "\\usepackage{CJK}\n"; } } + 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"; + } } @@ -3128,64 +3399,114 @@ string const BufferParams::loadFonts(LaTeXFeatures & features) const // variants are understood by both engines. However, // we want to provide support for at least TeXLive 2009 // (for XeTeX; LuaTeX is only supported as of v.2) + // 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"); string const texmapping = (features.runparams().flavor == OutputParams::XETEX) ? "Mapping=tex-text" : "Ligatures=TeX"; if (fontsRoman() != "default") { - os << "\\setmainfont[" << texmapping; - if (fonts_old_figures) + if (babelfonts) + os << "\\babelfont{rm}["; + else + os << "\\setmainfont["; + if (!font_roman_opts.empty()) + os << font_roman_opts << ','; + os << texmapping; + if (fonts_roman_osf) os << ",Numbers=OldStyle"; os << "]{" << parseFontName(fontsRoman()) << "}\n"; } if (fontsSans() != "default") { string const sans = parseFontName(fontsSans()); - if (fontsSansScale() != 100) - os << "\\setsansfont[Scale=" - << float(fontsSansScale()) / 100 - << "," << texmapping << "]{" + if (fontsSansScale() != 100) { + if (babelfonts) + os << "\\babelfont{sf}"; + else + os << "\\setsansfont"; + os << "[Scale=" + << float(fontsSansScale()) / 100 << ','; + if (fonts_sans_osf) + os << "Numbers=OldStyle,"; + if (!font_sans_opts.empty()) + os << font_sans_opts << ','; + os << texmapping << "]{" << sans << "}\n"; - else - os << "\\setsansfont[" << texmapping << "]{" + } else { + if (babelfonts) + os << "\\babelfont{sf}["; + else + os << "\\setsansfont["; + if (fonts_sans_osf) + os << "Numbers=OldStyle,"; + if (!font_sans_opts.empty()) + os << font_sans_opts << ','; + os << texmapping << "]{" << sans << "}\n"; + } } if (fontsTypewriter() != "default") { string const mono = parseFontName(fontsTypewriter()); - if (fontsTypewriterScale() != 100) - os << "\\setmonofont[Scale=" - << float(fontsTypewriterScale()) / 100 - << "]{" - << mono << "}\n"; - else - os << "\\setmonofont{" + if (fontsTypewriterScale() != 100) { + if (babelfonts) + os << "\\babelfont{tt}"; + else + os << "\\setmonofont"; + os << "[Scale=" + << float(fontsTypewriterScale()) / 100; + if (fonts_typewriter_osf) + os << ",Numbers=OldStyle"; + if (!font_typewriter_opts.empty()) + os << ',' << font_typewriter_opts; + os << "]{" << mono << "}\n"; + } else { + if (babelfonts) + os << "\\babelfont{tt}"; + else + os << "\\setmonofont"; + if (!font_typewriter_opts.empty() || fonts_typewriter_osf) { + os << '['; + if (fonts_typewriter_osf) + os << "Numbers=OldStyle"; + if (!font_typewriter_opts.empty()) { + if (fonts_typewriter_osf) + os << ','; + os << font_typewriter_opts; + } + os << ']'; + } + os << '{' << mono << "}\n"; + } } return os.str(); } // Tex Fonts - bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1"); + bool const ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1"); bool const dryrun = features.runparams().dryrun; bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default"); bool const nomath = (fontsMath() == "default"); // ROMAN FONTS os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode( - dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures, - nomath); + dryrun, ot1, complete, fonts_expert_sc, fonts_roman_osf, + nomath, font_roman_opts); // SANS SERIF os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode( - dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures, - nomath, fontsSansScale()); + dryrun, ot1, complete, fonts_expert_sc, fonts_sans_osf, + nomath, font_sans_opts, fontsSansScale()); // MONOSPACED/TYPEWRITER os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode( - dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures, - nomath, fontsTypewriterScale()); + dryrun, ot1, complete, fonts_expert_sc, fonts_typewriter_osf, + nomath, font_typewriter_opts, fontsTypewriterScale()); // MATH os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode( - dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures, + dryrun, ot1, complete, fonts_expert_sc, fonts_roman_osf, nomath); return os.str(); @@ -3195,16 +3516,12 @@ string const BufferParams::loadFonts(LaTeXFeatures & features) const Encoding const & BufferParams::encoding() const { // Main encoding for LaTeX output. - // - // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740). - // As the "flavor" is only known once export started, this - // cannot be handled here. Instead, runparams.encoding is set - // to ASCII in Buffer::makeLaTeXFile (for export) - // and Buffer::writeLaTeXSource (for preview). if (useNonTeXFonts) return *(encodings.fromLyXName("utf8-plain")); - if (inputenc == "auto" || inputenc == "default") + if (inputenc == "auto-legacy" || inputenc == "auto-legacy-plain") return *language->encoding(); + if (inputenc == "utf8" && language->lang() == "japanese") + return *(encodings.fromLyXName("utf8-platex")); Encoding const * const enc = encodings.fromLyXName(inputenc); if (enc) return *enc; @@ -3214,34 +3531,17 @@ Encoding const & BufferParams::encoding() const } -bool BufferParams::addCiteEngine(string const & engine) -{ - LayoutModuleList::const_iterator it = cite_engine_.begin(); - LayoutModuleList::const_iterator en = cite_engine_.end(); - for (; it != en; ++it) - if (*it == engine) - return false; - cite_engine_.push_back(engine); - return true; -} - - -bool BufferParams::addCiteEngine(vector const & engine) -{ - vector::const_iterator it = engine.begin(); - vector::const_iterator en = engine.end(); - bool ret = true; - for (; it != en; ++it) - if (!addCiteEngine(*it)) - ret = false; - return ret; -} - - string const & BufferParams::defaultBiblioStyle() const { - map bs = documentClass().defaultBiblioStyle(); - return bs[theCiteEnginesList.getTypeAsString(citeEngineType())]; + if (!biblio_style.empty()) + return biblio_style; + + map const & bs = documentClass().defaultBiblioStyle(); + auto cit = bs.find(theCiteEnginesList.getTypeAsString(citeEngineType())); + if (cit != bs.end()) + return cit->second; + else + return empty_string(); } @@ -3265,20 +3565,6 @@ string BufferParams::getCiteAlias(string const & s) const } -void BufferParams::setCiteEngine(string const & engine) -{ - clearCiteEngine(); - addCiteEngine(engine); -} - - -void BufferParams::setCiteEngine(vector const & engine) -{ - clearCiteEngine(); - addCiteEngine(engine); -} - - vector BufferParams::citeCommands() const { static CitationStyle const default_style; @@ -3301,14 +3587,48 @@ vector BufferParams::citeStyles() const } -string const & BufferParams::bibtexCommand() const +string const BufferParams::bibtexCommand() const { + // Return document-specific setting if available if (bibtex_command != "default") return bibtex_command; - else if (encoding().package() == Encoding::japanese) - return lyxrc.jbibtex_command; - else + + // If we have "default" in document settings, consult the prefs + // 1. Japanese (uses a specific processor) + if (encoding().package() == Encoding::japanese) { + if (lyxrc.jbibtex_command != "automatic") + // Return the specified program, if "automatic" is not set + return lyxrc.jbibtex_command; + else if (!useBiblatex()) { + // With classic BibTeX, return pbibtex, jbibtex, bibtex + if (lyxrc.jbibtex_alternatives.find("pbibtex") != lyxrc.jbibtex_alternatives.end()) + return "pbibtex"; + if (lyxrc.jbibtex_alternatives.find("jbibtex") != lyxrc.jbibtex_alternatives.end()) + return "jbibtex"; + return "bibtex"; + } + } + // 2. All other languages + else if (lyxrc.bibtex_command != "automatic") + // Return the specified program, if "automatic" is not set return lyxrc.bibtex_command; + + // 3. Automatic: find the most suitable for the current cite framework + if (useBiblatex()) { + // For Biblatex, we prefer biber (also for Japanese) + // and fall back to bibtex8 and, as last resort, bibtex + if (lyxrc.bibtex_alternatives.find("biber") != lyxrc.bibtex_alternatives.end()) + return "biber"; + else if (lyxrc.bibtex_alternatives.find("bibtex8") != lyxrc.bibtex_alternatives.end()) + return "bibtex8"; + } + return "bibtex"; +} + + +bool BufferParams::useBiblatex() const +{ + return theCiteEnginesList[citeEngine()]->getCiteFramework() == "biblatex"; } @@ -3318,4 +3638,32 @@ void BufferParams::invalidateConverterCache() const pimpl_->isViewCacheValid = false; } + +// We shouldn't need to reset the params here, since anything +// we need will be recopied. +void BufferParams::copyForAdvFR(const BufferParams & bp) +{ + string const & lang = bp.language->lang(); + setLanguage(lang); + layout_modules_ = bp.layout_modules_; + string const & doc_class = bp.documentClass().name(); + setBaseClass(doc_class); +} + + +void BufferParams::setBibFileEncoding(string const & file, string const & enc) +{ + bib_encodings[file] = enc; +} + + +string const BufferParams::bibFileEncoding(string const & file) const +{ + if (bib_encodings.find(file) == bib_encodings.end()) + return string(); + return bib_encodings.find(file)->second; +} + + + } // namespace lyx