X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferParams.cpp;h=bb2391ca115926533f3487f9fd6c511f0ebb8dba;hb=3d4076b598deb18660e50ec9c327efc3b15f15d0;hp=fab62fb9ec4a5682a320435a964741e2994191d9;hpb=fa8dae4201fc25da685a21de0f8968678df8f119;p=lyx.git diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp index fab62fb9ec..bb2391ca11 100644 --- a/src/BufferParams.cpp +++ b/src/BufferParams.cpp @@ -24,11 +24,13 @@ #include "Bullet.h" #include "Color.h" #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 "ModuleList.h" #include "Font.h" #include "Lexer.h" @@ -258,22 +260,20 @@ PackageTranslator const & packagetranslator() // Cite engine -typedef Translator CiteEngineTranslator; +typedef Translator CiteEngineTypeTranslator; -CiteEngineTranslator const init_citeenginetranslator() +CiteEngineTypeTranslator const init_citeenginetypetranslator() { - CiteEngineTranslator translator("basic", ENGINE_BASIC); - translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL); - translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR); - translator.addPair("jurabib", ENGINE_JURABIB); + CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR); + translator.addPair("numerical", ENGINE_TYPE_NUMERICAL); return translator; } -CiteEngineTranslator const & citeenginetranslator() +CiteEngineTypeTranslator const & citeenginetypetranslator() { - static CiteEngineTranslator translator = init_citeenginetranslator(); + static CiteEngineTypeTranslator translator = init_citeenginetypetranslator(); return translator; } @@ -335,8 +335,7 @@ BufferParams::Impl::Impl() BufferParams::Impl * BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr) { - LASSERT(ptr, /**/); - + LBUFERR(ptr); return new BufferParams::Impl(*ptr); } @@ -360,11 +359,9 @@ BufferParams::BufferParams() papersize = PAPER_DEFAULT; orientation = ORIENTATION_PORTRAIT; use_geometry = false; - use_amsmath = package_auto; - use_esint = package_auto; - use_mhchem = package_auto; - use_mathdots = package_auto; - cite_engine_ = ENGINE_BASIC; + cite_engine_.push_back("basic"); + cite_engine_type_ = ENGINE_TYPE_NUMERICAL; + biblio_style = "plain"; use_bibtopic = false; use_indices = false; trackChanges = false; @@ -375,18 +372,20 @@ BufferParams::BufferParams() tocdepth = 3; language = default_language; fontenc = "global"; - fontsRoman = "default"; - fontsSans = "default"; - fontsTypewriter = "default"; - fontsDefaultFamily = "default"; - useXetex = false; - fontsSC = false; - fontsOSF = false; - fontsSansScale = 100; - fontsTypewriterScale = 100; + fonts_roman = "default"; + fonts_sans = "default"; + fonts_typewriter = "default"; + fonts_math = "auto"; + fonts_default_family = "default"; + useNonTeXFonts = false; + fonts_expert_sc = false; + fonts_old_figures = false; + fonts_sans_scale = 100; + fonts_typewriter_scale = 100; inputenc = "auto"; - graphicsDriver = "default"; - defaultOutputFormat = "default"; + lang_package = "default"; + graphics_driver = "default"; + default_output_format = "default"; bibtex_command = "default"; index_command = "default"; sides = OneSide; @@ -394,6 +393,7 @@ BufferParams::BufferParams() listings_params = string(); pagestyle = "default"; suppress_date = false; + justification = true; // no color is the default (white) backgroundcolor = lyx::rgbFromHexName("#ffffff"); isbackgroundcolor = false; @@ -413,6 +413,7 @@ BufferParams::BufferParams() html_be_strict = false; html_math_output = MathML; html_math_img_scale = 1.0; + html_css_as_file = false; output_sync = false; use_refstyle = true; @@ -421,11 +422,56 @@ BufferParams::BufferParams() docstring BufferParams::B_(string const & l10n) const { - LASSERT(language, /**/); + LASSERT(language, return from_utf8(l10n)); return getMessages(language->code()).get(l10n); } +BufferParams::Package BufferParams::use_package(std::string const & p) const +{ + PackageMap::const_iterator it = use_packages.find(p); + if (it == use_packages.end()) + return package_auto; + return it->second; +} + + +void BufferParams::use_package(std::string const & p, BufferParams::Package u) +{ + use_packages[p] = u; +} + + +map const & BufferParams::auto_packages() +{ + static map packages; + if (packages.empty()) { + // adding a package here implies a file format change! + packages["amsmath"] = + N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas"); + packages["amssymb"] = + N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas"); + packages["cancel"] = + N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas"); + packages["esint"] = + N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas"); + packages["mathdots"] = + N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas"); + packages["mathtools"] = + N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas"); + packages["mhchem"] = + N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas"); + packages["stackrel"] = + N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas"); + packages["stmaryrd"] = + N_("The LaTeX package stmaryrd is only used if symbols from the St Mary's Road symbol font for theoretical computer science are inserted into formulas"); + packages["undertilde"] = + N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'"); + } + return packages; +} + + AuthorList & BufferParams::authors() { return pimpl_->authorlist; @@ -464,28 +510,28 @@ IndicesList const & BufferParams::indiceslist() const Bullet & BufferParams::temp_bullet(lyx::size_type const index) { - LASSERT(index < 4, /**/); + LASSERT(index < 4, return pimpl_->temp_bullets[0]); return pimpl_->temp_bullets[index]; } Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const { - LASSERT(index < 4, /**/); + LASSERT(index < 4, return pimpl_->temp_bullets[0]); return pimpl_->temp_bullets[index]; } Bullet & BufferParams::user_defined_bullet(lyx::size_type const index) { - LASSERT(index < 4, /**/); + LASSERT(index < 4, return pimpl_->temp_bullets[0]); return pimpl_->user_defined_bullets[index]; } Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const { - LASSERT(index < 4, /**/); + LASSERT(index < 4, return pimpl_->temp_bullets[0]); return pimpl_->user_defined_bullets[index]; } @@ -547,22 +593,23 @@ string BufferParams::readToken(Lexer & lex, string const & token, lex.next(); string const classname = lex.getString(); // if there exists a local layout file, ignore the system one - // NOTE: in this case, the textclass (.cls file) is assumed to + // NOTE: in this case, the textclass (.cls file) is assumed to // be available. string tcp; LayoutFileList & bcl = LayoutFileList::get(); - if (tcp.empty() && !filepath.empty()) + if (!filepath.empty()) tcp = bcl.addLocalLayout(classname, filepath.absFileName()); + // that returns non-empty if a "local" layout file is found. if (!tcp.empty()) setBaseClass(tcp); else setBaseClass(classname); - // We assume that a tex class exists for local or unknown + // We assume that a tex class exists for local or unknown // layouts so this warning, will only be given for system layouts. if (!baseClass()->isTeXClassAvailable()) { - docstring const desc = + docstring const desc = translateIfPossible(from_utf8(baseClass()->description())); - docstring const prereqs = + docstring const prereqs = from_utf8(baseClass()->prerequisites()); docstring const msg = bformat(_("The selected document class\n" @@ -572,8 +619,8 @@ string BufferParams::readToken(Lexer & lex, string const & token, "document cannot be compiled until the following\n" "prerequisites are installed:\n" "\t%2$s\n" - "See section 3.1.2.2 of the User's Guide for\n" - "more information."), desc, prereqs); + "See section 3.1.2.2 (Class Availability) of the\n" + "User's Guide for more information."), desc, prereqs); frontend::Alert::warning(_("Document class not available"), msg); } @@ -599,14 +646,19 @@ string BufferParams::readToken(Lexer & lex, string const & token, master = lex.getString(); } else if (token == "\\suppress_date") { lex >> suppress_date; + } else if (token == "\\justification") { + lex >> justification; } else if (token == "\\language") { readLanguage(lex); + } else if (token == "\\language_package") { + lex.eatLine(); + lang_package = lex.getString(); } else if (token == "\\inputencoding") { lex >> inputenc; } else if (token == "\\graphics") { readGraphicsDriver(lex); } else if (token == "\\default_output_format") { - lex >> defaultOutputFormat; + lex >> default_output_format; } else if (token == "\\bibtex_command") { lex.eatLine(); bibtex_command = lex.getString(); @@ -618,27 +670,30 @@ string BufferParams::readToken(Lexer & lex, string const & token, fontenc = lex.getString(); } else if (token == "\\font_roman") { lex.eatLine(); - fontsRoman = lex.getString(); + fonts_roman = lex.getString(); } else if (token == "\\font_sans") { lex.eatLine(); - fontsSans = lex.getString(); + fonts_sans = lex.getString(); } else if (token == "\\font_typewriter") { lex.eatLine(); - fontsTypewriter = lex.getString(); + fonts_typewriter = lex.getString(); + } else if (token == "\\font_math") { + lex.eatLine(); + fonts_math = lex.getString(); } else if (token == "\\font_default_family") { - lex >> fontsDefaultFamily; - } else if (token == "\\use_xetex") { - lex >> useXetex; + lex >> fonts_default_family; + } else if (token == "\\use_non_tex_fonts") { + lex >> useNonTeXFonts; } else if (token == "\\font_sc") { - lex >> fontsSC; + lex >> fonts_expert_sc; } else if (token == "\\font_osf") { - lex >> fontsOSF; + lex >> fonts_old_figures; } else if (token == "\\font_sf_scale") { - lex >> fontsSansScale; + lex >> fonts_sans_scale; } else if (token == "\\font_tt_scale") { - lex >> fontsTypewriterScale; + lex >> fonts_typewriter_scale; } else if (token == "\\font_cjk") { - lex >> fontsCJK; + lex >> fonts_cjk; } else if (token == "\\paragraph_separation") { string parsep; lex >> parsep; @@ -664,26 +719,23 @@ string BufferParams::readToken(Lexer & lex, string const & token, papersize = papersizetranslator().find(ppsize); } else if (token == "\\use_geometry") { lex >> use_geometry; - } else if (token == "\\use_amsmath") { - int use_ams; - lex >> use_ams; - use_amsmath = packagetranslator().find(use_ams); - } else if (token == "\\use_esint") { - int useesint; - lex >> useesint; - use_esint = packagetranslator().find(useesint); - } else if (token == "\\use_mhchem") { - int usemhchem; - lex >> usemhchem; - use_mhchem = packagetranslator().find(usemhchem); - } else if (token == "\\use_mathdots") { - int usemathdots; - lex >> usemathdots; - use_mathdots = packagetranslator().find(usemathdots); + } else if (token == "\\use_package") { + string package; + int use; + lex >> package; + lex >> use; + use_package(package, packagetranslator().find(use)); } else if (token == "\\cite_engine") { - string engine; - lex >> engine; - cite_engine_ = citeenginetranslator().find(engine); + lex.eatLine(); + vector engine = getVectorFromString(lex.getString()); + setCiteEngine(engine); + } else if (token == "\\cite_engine_type") { + string engine_type; + lex >> engine_type; + cite_engine_type_ = citeenginetypetranslator().find(engine_type); + } else if (token == "\\biblio_style") { + lex.eatLine(); + biblio_style = lex.getString(); } else if (token == "\\use_bibtopic") { lex >> use_bibtopic; } else if (token == "\\use_indices") { @@ -776,10 +828,12 @@ string BufferParams::readToken(Lexer & lex, string const & token, lex.eatLine(); string color = lex.getString(); notefontcolor = lyx::rgbFromHexName(color); + lcolor.setColor("notefontcolor", color); } else if (token == "\\boxbgcolor") { lex.eatLine(); string color = lex.getString(); boxbgcolor = lyx::rgbFromHexName(color); + lcolor.setColor("boxbgcolor", color); } else if (token == "\\paperwidth") { lex >> paperwidth; } else if (token == "\\paperheight") { @@ -846,6 +900,8 @@ string BufferParams::readToken(Lexer & lex, string const & token, html_math_output = static_cast(temp); } else if (token == "\\html_be_strict") { lex >> html_be_strict; + } else if (token == "\\html_css_as_file") { + lex >> html_css_as_file; } else if (token == "\\html_math_img_scale") { lex >> html_math_img_scale; } else if (token == "\\html_latex_start") { @@ -861,7 +917,7 @@ string BufferParams::readToken(Lexer & lex, string const & token, } else if (token == "\\use_refstyle") { lex >> use_refstyle; } else { - lyxerr << "BufferParams::readToken(): Unknown token: " << + lyxerr << "BufferParams::readToken(): Unknown token: " << token << endl; return token; } @@ -893,40 +949,40 @@ void BufferParams::writeFile(ostream & os) const } // use the class options defined in the layout? - os << "\\use_default_options " + os << "\\use_default_options " << convert(use_default_options) << "\n"; // the master document if (!master.empty()) { os << "\\master " << master << '\n'; } - + // removed modules - if (!removedModules_.empty()) { + if (!removed_modules_.empty()) { os << "\\begin_removed_modules" << '\n'; - list::const_iterator it = removedModules_.begin(); - list::const_iterator en = removedModules_.end(); - for (; it != en; it++) + list::const_iterator it = removed_modules_.begin(); + list::const_iterator en = removed_modules_.end(); + for (; it != en; ++it) os << *it << '\n'; os << "\\end_removed_modules" << '\n'; } // the modules - if (!layoutModules_.empty()) { + if (!layout_modules_.empty()) { os << "\\begin_modules" << '\n'; - LayoutModuleList::const_iterator it = layoutModules_.begin(); - LayoutModuleList::const_iterator en = layoutModules_.end(); - for (; it != en; it++) + LayoutModuleList::const_iterator it = layout_modules_.begin(); + LayoutModuleList::const_iterator en = layout_modules_.end(); + for (; it != en; ++it) os << *it << '\n'; os << "\\end_modules" << '\n'; } // includeonly - if (!includedChildren_.empty()) { + if (!included_children_.empty()) { os << "\\begin_includeonly" << '\n'; - list::const_iterator it = includedChildren_.begin(); - list::const_iterator en = includedChildren_.end(); - for (; it != en; it++) + list::const_iterator it = included_children_.begin(); + list::const_iterator en = included_children_.end(); + for (; it != en; ++it) os << *it << '\n'; os << "\\end_includeonly" << '\n'; } @@ -935,7 +991,7 @@ void BufferParams::writeFile(ostream & os) const // local layout information if (!local_layout.empty()) { - // remove '\n' from the end + // remove '\n' from the end string const tmplocal = rtrim(local_layout, "\n"); os << "\\begin_local_layout\n" << tmplocal @@ -945,23 +1001,25 @@ void BufferParams::writeFile(ostream & os) const // then the text parameters if (language != ignore_language) os << "\\language " << language->lang() << '\n'; - os << "\\inputencoding " << inputenc + os << "\\language_package " << lang_package + << "\n\\inputencoding " << inputenc << "\n\\fontencoding " << fontenc - << "\n\\font_roman " << fontsRoman - << "\n\\font_sans " << fontsSans - << "\n\\font_typewriter " << fontsTypewriter - << "\n\\font_default_family " << fontsDefaultFamily - << "\n\\use_xetex " << convert(useXetex) - << "\n\\font_sc " << convert(fontsSC) - << "\n\\font_osf " << convert(fontsOSF) - << "\n\\font_sf_scale " << fontsSansScale - << "\n\\font_tt_scale " << fontsTypewriterScale + << "\n\\font_roman " << fonts_roman + << "\n\\font_sans " << fonts_sans + << "\n\\font_typewriter " << fonts_typewriter + << "\n\\font_math " << fonts_math + << "\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 + << "\n\\font_tt_scale " << fonts_typewriter_scale << '\n'; - if (!fontsCJK.empty()) { - os << "\\font_cjk " << fontsCJK << '\n'; + if (!fonts_cjk.empty()) { + os << "\\font_cjk " << fonts_cjk << '\n'; } - os << "\n\\graphics " << graphicsDriver << '\n'; - os << "\\default_output_format " << defaultOutputFormat << '\n'; + os << "\\graphics " << graphics_driver << '\n'; + os << "\\default_output_format " << default_output_format << '\n'; os << "\\output_sync " << output_sync << '\n'; if (!output_sync_macro.empty()) os << "\\output_sync_macro \"" << output_sync_macro << "\"\n"; @@ -977,17 +1035,35 @@ void BufferParams::writeFile(ostream & os) const pdfoptions().writeFile(os); os << "\\papersize " << string_papersize[papersize] - << "\n\\use_geometry " << convert(use_geometry) - << "\n\\use_amsmath " << use_amsmath - << "\n\\use_esint " << use_esint - << "\n\\use_mhchem " << use_mhchem - << "\n\\use_mathdots " << use_mathdots - << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_) + << "\n\\use_geometry " << convert(use_geometry); + map const & packages = auto_packages(); + for (map::const_iterator it = packages.begin(); + it != packages.end(); ++it) + os << "\n\\use_package " << it->first << ' ' + << use_package(it->first); + + 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 { + os << "basic"; + } + + os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_) + << "\n\\biblio_style " << biblio_style << "\n\\use_bibtopic " << convert(use_bibtopic) << "\n\\use_indices " << convert(use_indices) << "\n\\paperorientation " << string_orientation[orientation] << "\n\\suppress_date " << convert(suppress_date) - << "\n\\use_refstyle " << use_refstyle + << "\n\\justification " << convert(justification) + << "\n\\use_refstyle " << use_refstyle << '\n'; if (isbackgroundcolor == true) os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n'; @@ -1047,7 +1123,7 @@ void BufferParams::writeFile(ostream & os) const os << "\\footskip " << VSpace(footskip).asLyXCommand() << '\n'; if (!columnsep.empty()) - os << "\\columnsep " + os << "\\columnsep " << VSpace(columnsep).asLyXCommand() << '\n'; os << "\\secnumdepth " << secnumdepth << "\n\\tocdepth " << tocdepth @@ -1083,10 +1159,11 @@ void BufferParams::writeFile(ostream & os) const } os << "\\tracking_changes " << convert(trackChanges) << '\n' - << "\\output_changes " << convert(outputChanges) << '\n' - << "\\html_math_output " << html_math_output << '\n' - << "\\html_be_strict " << convert(html_be_strict) << '\n'; - + << "\\output_changes " << convert(outputChanges) << '\n' + << "\\html_math_output " << html_math_output << '\n' + << "\\html_css_as_file " << html_css_as_file << '\n' + << "\\html_be_strict " << convert(html_be_strict) << '\n'; + if (html_math_img_scale != 1.0) os << "\\html_math_img_scale " << convert(html_math_img_scale) << '\n'; if (!html_latex_start.empty()) @@ -1102,6 +1179,9 @@ void BufferParams::validate(LaTeXFeatures & features) const { features.require(documentClass().requires()); + if (columns > 1 && language->rightToLeft()) + features.require("rtloutputdblcol"); + if (outputChanges) { bool dvipost = LaTeXFeatures::isAvailable("dvipost"); bool xcolorulem = LaTeXFeatures::isAvailable("ulem") && @@ -1109,6 +1189,7 @@ void BufferParams::validate(LaTeXFeatures & features) const switch (features.runparams().flavor) { case OutputParams::LATEX: + case OutputParams::DVILUATEX: if (dvipost) { features.require("ct-dvipost"); features.require("dvipost"); @@ -1120,6 +1201,7 @@ void BufferParams::validate(LaTeXFeatures & features) const features.require("ct-none"); } break; + case OutputParams::LUATEX: case OutputParams::PDFLATEX: case OutputParams::XETEX: if (xcolorulem) { @@ -1127,7 +1209,7 @@ void BufferParams::validate(LaTeXFeatures & features) const features.require("ulem"); features.require("xcolor"); // improves color handling in PDF output - features.require("pdfcolmk"); + features.require("pdfcolmk"); } else { features.require("ct-none"); } @@ -1141,16 +1223,16 @@ void BufferParams::validate(LaTeXFeatures & features) const if (float_placement.find('H') != string::npos) features.require("float"); - // AMS Style is at document level - if (use_amsmath == package_on - || documentClass().provides("amsmath")) - features.require("amsmath"); - if (use_esint == package_on) - features.require("esint"); - if (use_mhchem == package_on) - features.require("mhchem"); - if (use_mathdots == package_on) - features.require("mathdots"); + for (PackageMap::const_iterator it = use_packages.begin(); + it != use_packages.end(); ++it) { + if (it->first == "amsmath") { + // AMS Style is at document level + if (it->second == package_on || + features.isProvided("amsmath")) + features.require(it->first); + } else if (it->second == package_on) + features.require(it->first); + } // Document-level line spacing if (spacing().getSpace() != Spacing::Single && !spacing().isDefault()) @@ -1159,7 +1241,7 @@ void BufferParams::validate(LaTeXFeatures & features) const // the bullet shapes are buffer level not paragraph level // so they are tested here for (int i = 0; i < 4; ++i) { - if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i]) + if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i]) continue; int const font = user_defined_bullet(i).getFont(); if (font == 0) { @@ -1187,19 +1269,32 @@ void BufferParams::validate(LaTeXFeatures & features) const features.require("color"); } - if (useXetex) + // some languages are only available via polyglossia + if (features.runparams().flavor == OutputParams::XETEX + && (features.hasPolyglossiaExclusiveLanguages() + || useNonTeXFonts)) features.require("polyglossia"); - if (language->lang() == "vietnamese") - features.require("vietnamese"); - else if (language->lang() == "japanese") - features.require("japanese"); + if (useNonTeXFonts && fonts_math != "auto") + features.require("unicode-math"); + + if (!language->requires().empty()) + features.require(language->requires()); } -bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, - TexRow & texrow, FileName const & filepath) const +bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, + FileName const & filepath) const { + // 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 + // Do not try to load any other package before the document class, unless you + // have a thorough understanding of the LATEX internals and know exactly what you + // are doing! + if (features.mustProvide("fix-cm")) + os << "\\RequirePackage{fix-cm}\n"; + os << "\\documentclass"; DocumentClass const & tclass = documentClass(); @@ -1304,17 +1399,18 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, features.useLanguage(default_language); ostringstream language_options; - bool const use_babel = features.useBabel() && !tclass.provides("babel"); + 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)) { - language_options << features.getLanguages(); + language_options << features.getBabelLanguages(); if (!language->babel().empty()) { if (!language_options.str().empty()) language_options << ','; language_options << language->babel(); } - if (global && !features.needBabelLangOptions()) + if (global && !features.needBabelLangOptions() + && !language_options.str().empty()) clsoptions << language_options.str() << ','; } @@ -1335,64 +1431,77 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, } os << '{' << from_ascii(tclass.latexname()) << "}\n"; - texrow.newline(); // end of \documentclass defs - if (useXetex) { + // if we use fontspec, we have to load the AMS packages here + string const ams = features.loadAMSPackages(); + if (useNonTeXFonts && !ams.empty()) + os << from_ascii(ams); + + if (useNonTeXFonts) { os << "\\usepackage{fontspec}\n"; - texrow.newline(); + if (features.mustProvide("unicode-math") + && features.isAvailable("unicode-math")) + os << "\\usepackage{unicode-math}\n"; } // font selection must be done before loading fontenc.sty - string const fonts = - loadFonts(fontsRoman, fontsSans, - fontsTypewriter, fontsSC, fontsOSF, - fontsSansScale, fontsTypewriterScale, useXetex); - if (!fonts.empty()) { - os << from_ascii(fonts); - texrow.newline(); - } - if (fontsDefaultFamily != "default") + string const fonts = loadFonts(features); + if (!fonts.empty()) + os << from_utf8(fonts); + + if (fonts_default_family != "default") os << "\\renewcommand{\\familydefault}{\\" - << from_ascii(fontsDefaultFamily) << "}\n"; + << from_ascii(fonts_default_family) << "}\n"; // set font encoding // for arabic_arabi and farsi we also need to load the LAE and // LFE encoding - // XeTeX works without fontenc + // XeTeX and LuaTeX (with OS fonts) work without fontenc if (font_encoding() != "default" && language->lang() != "japanese" - && !useXetex && !tclass.provides("fontenc")) { + && !useNonTeXFonts && !features.isProvided("fontenc")) { + docstring extra_encoding; + if (features.mustProvide("textgreek")) + extra_encoding += from_ascii("LGR"); + if (features.mustProvide("textcyr")) { + if (!extra_encoding.empty()) + extra_encoding.push_back(','); + extra_encoding += from_ascii("T2A"); + } + if (!extra_encoding.empty() && !font_encoding().empty()) + extra_encoding.push_back(','); size_t fars = language_options.str().find("farsi"); size_t arab = language_options.str().find("arabic"); if (language->lang() == "arabic_arabi" || language->lang() == "farsi" || fars != string::npos || arab != string::npos) { - os << "\\usepackage[" << from_ascii(font_encoding()) + os << "\\usepackage[" << extra_encoding + << from_ascii(font_encoding()) << ",LFE,LAE]{fontenc}\n"; - texrow.newline(); } else { - os << "\\usepackage[" << from_ascii(font_encoding()) + os << "\\usepackage[" << extra_encoding + << from_ascii(font_encoding()) << "]{fontenc}\n"; - texrow.newline(); } } // handle inputenc etc. - writeEncodingPreamble(os, features, texrow); + writeEncodingPreamble(os, features); // includeonly - if (!features.runparams().includeall && !includedChildren_.empty()) { + if (!features.runparams().includeall && !included_children_.empty()) { os << "\\includeonly{"; - list::const_iterator it = includedChildren_.begin(); + list::const_iterator it = included_children_.begin(); + list::const_iterator en = included_children_.end(); bool first = true; - for (; it != includedChildren_.end() ; ++it) { + for (; it != en; ++it) { string incfile = *it; FileName inc = makeAbsPath(incfile, filepath.absFileName()); string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")). mangledFileName(); if (!features.runparams().nice) incfile = mangled; - // \includeonly doesn't want an extension + // \includeonly doesn't want an extension incfile = changeExtension(incfile, string()); incfile = support::latex_path(incfile); if (!incfile.empty()) { @@ -1405,28 +1514,22 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, os << "}\n"; } - if (!listings_params.empty() || features.isRequired("listings")) { + if (!listings_params.empty() || features.isRequired("listings")) os << "\\usepackage{listings}\n"; - texrow.newline(); - } + if (!listings_params.empty()) { os << "\\lstset{"; - // do not test validity because listings_params is + // do not test validity because listings_params is // supposed to be valid string par = InsetListingsParams(listings_params).separatedParams(true); // we can't support all packages, but we should load the color package if (par.find("\\color", 0) != string::npos) features.require("color"); - os << from_utf8(par); - // count the number of newlines - for (size_t i = 0; i < par.size(); ++i) - if (par[i] == '\n') - texrow.newline(); - os << "}\n"; - texrow.newline(); + os << from_utf8(par) + << "}\n"; } - if (!tclass.provides("geometry") + if (!features.isProvided("geometry") && (use_geometry || nonstandard_papersize)) { odocstringstream ods; if (!getGraphicsDriver("geometry").empty()) @@ -1535,65 +1638,14 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, case PAPER_JISB6: ods << ",b6j"; break; - default: - // default papersize ie PAPER_DEFAULT - switch (lyxrc.default_papersize) { - case PAPER_DEFAULT: // keep compiler happy - case PAPER_USLETTER: - ods << ",letterpaper"; - break; - case PAPER_USLEGAL: - ods << ",legalpaper"; - break; - case PAPER_USEXECUTIVE: - ods << ",executivepaper"; - break; - case PAPER_A3: - ods << ",a3paper"; - break; - case PAPER_A4: - ods << ",a4paper"; - break; - case PAPER_A5: - ods << ",a5paper"; - break; - case PAPER_B5: - ods << ",b5paper"; - break; - case PAPER_A0: - case PAPER_A1: - case PAPER_A2: - case PAPER_A6: - case PAPER_B0: - case PAPER_B1: - case PAPER_B2: - case PAPER_B3: - case PAPER_B4: - case PAPER_B6: - case PAPER_C0: - case PAPER_C1: - case PAPER_C2: - case PAPER_C3: - case PAPER_C4: - case PAPER_C5: - case PAPER_C6: - case PAPER_JISB0: - case PAPER_JISB1: - case PAPER_JISB2: - case PAPER_JISB3: - case PAPER_JISB4: - case PAPER_JISB5: - case PAPER_JISB6: - case PAPER_CUSTOM: - break; - } + case PAPER_DEFAULT: + break; } docstring const g_options = trim(ods.str(), ","); os << "\\usepackage"; if (!g_options.empty()) os << '[' << g_options << ']'; os << "{geometry}\n"; - texrow.newline(); // output this only if use_geometry is true if (use_geometry) { os << "\\geometry{verbose"; @@ -1614,28 +1666,23 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, if (!columnsep.empty()) os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString()); os << "}\n"; - texrow.newline(); } } else if (orientation == ORIENTATION_LANDSCAPE || papersize != PAPER_DEFAULT) { features.require("papersize"); } - if (tokenPos(tclass.opt_pagestyle(), - '|', pagestyle) >= 0) { - if (pagestyle == "fancy") { + if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) { + if (pagestyle == "fancy") os << "\\usepackage{fancyhdr}\n"; - texrow.newline(); - } os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n"; - texrow.newline(); } // only output when the background color is not default if (isbackgroundcolor == true) { // only require color here, the background color will be defined // in LaTeXFeatures.cpp to avoid interferences with the LaTeX - // package pdfpages + // package pdfpages features.require("color"); features.require("pagecolor"); } @@ -1644,7 +1691,7 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, if (isfontcolor == true) { // only require color here, the font color will be defined // in LaTeXFeatures.cpp to avoid interferences with the LaTeX - // package pdfpages + // package pdfpages features.require("color"); features.require("fontcolor"); } @@ -1655,13 +1702,11 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, os << "\\setcounter{secnumdepth}{" << secnumdepth << "}\n"; - texrow.newline(); } if (tocdepth != tclass.tocdepth()) { os << "\\setcounter{tocdepth}{" << tocdepth << "}\n"; - texrow.newline(); } } @@ -1686,22 +1731,20 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, os << "\\setlength{\\parskip}{\\medskipamount}\n"; break; } - texrow.newline(); os << "\\setlength{\\parindent}{0pt}\n"; - texrow.newline(); } else { // when separation by indentation // only output something when a width is given if (getIndentation().asLyXCommand() != "default") { os << "\\setlength{\\parindent}{" - << from_utf8(getIndentation().asLatexCommand()) + << from_utf8(getIndentation().asLatexCommand()) << "}\n"; - texrow.newline(); } } // Now insert the LyX specific LaTeX commands... docstring lyxpreamble; + features.resolveAlternatives(); if (output_sync) { if (!output_sync_macro.empty()) @@ -1719,11 +1762,13 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, // we decided therefore to load color always before babel, see // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html lyxpreamble += from_ascii(features.getColorOptions()); - - // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them. + + // If we use hyperref, jurabib, japanese, varioref or vietnamese, + // we have to call babel before if (use_babel && (features.isRequired("jurabib") || features.isRequired("hyperref") + || features.isRequired("varioref") || features.isRequired("vietnamese") || features.isRequired("japanese"))) { // FIXME UNICODE @@ -1741,16 +1786,27 @@ bool BufferParams::writeLaTeX(odocstream & 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)); + } lyxpreamble += "\\newindex["; - lyxpreamble += iit->index(); + lyxpreamble += indexname_latex.first; lyxpreamble += "]{"; - lyxpreamble += iit->shortcut(); + lyxpreamble += escape(iit->shortcut()); lyxpreamble += "}\n"; } } // Line spacing - lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace"))); + lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace"))); // PDF support. // * Hyperref manual: "Make sure it comes last of your loaded @@ -1762,23 +1818,28 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, // avoid errors with algorithm floats. // use hyperref explicitly if it is required if (features.isRequired("hyperref")) { - // pass what we have to stream here, since we need + // pass what we have to stream here, since we need // to access the stream itself in PDFOptions. os << lyxpreamble; - int lines = - int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n')); - OutputParams tmp_params = features.runparams(); - lines += pdfoptions().writeLaTeX(tmp_params, os, - documentClass().provides("hyperref")); - texrow.newlines(lines); + pdfoptions().writeLaTeX(tmp_params, os, + features.isProvided("hyperref")); // set back for the rest lyxpreamble.clear(); + // correctly break URLs with hyperref and dvi output + if (features.runparams().flavor == OutputParams::LATEX + && features.isAvailable("breakurl")) + lyxpreamble += "\\usepackage{breakurl}\n"; } else if (features.isRequired("nameref")) // hyperref loads this automatically lyxpreamble += "\\usepackage{nameref}\n"; + // bibtopic needs to be loaded after hyperref. + // the dot provides the aux file naming which LyX can detect. + if (features.mustProvide("bibtopic")) + lyxpreamble += "\\usepackage[dot]{bibtopic}\n"; + // Will be surrounded by \makeatletter and \makeatother when not empty docstring atlyxpreamble; @@ -1866,9 +1927,10 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, + atlyxpreamble + "\\makeatother\n\n"; // We try to load babel late, in case it interferes with other packages. - // Jurabib and Hyperref have to be called after babel, though. + // Jurabib, hyperref and varioref have to be called after babel, though. if (use_babel && !features.isRequired("jurabib") && !features.isRequired("hyperref") + && !features.isRequired("varioref") && !features.isRequired("vietnamese") && !features.isRequired("japanese")) { // FIXME UNICODE @@ -1878,49 +1940,48 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features, lyxpreamble += from_utf8(features.getBabelPostsettings()); } - // FIXME Polyglossia? - docstring const i18npreamble = features.getTClassI18nPreamble(use_babel); - if (!i18npreamble.empty()) - lyxpreamble += i18npreamble + '\n'; - - int const nlines = - int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n')); - texrow.newlines(nlines); - - os << lyxpreamble; + // xunicode needs to be loaded at least after amsmath, amssymb, + // esint and the other packages that provide special glyphs + if (features.runparams().flavor == OutputParams::XETEX) + lyxpreamble += "\\usepackage{xunicode}\n"; - // these packages (xunicode, for that matter) need to be loaded at least - // after amsmath, amssymb, esint and the other packages that provide - // special glyphs - if (useXetex) { - os << "\\usepackage{xunicode}\n"; - texrow.newline(); - os << "\\usepackage{xltxtra}\n"; - texrow.newline(); - } - // Polyglossia must be loaded after xltxtra + // Polyglossia must be loaded last if (use_polyglossia) { // call the package - os << "\\usepackage{polyglossia}\n"; - texrow.newline(); + lyxpreamble += "\\usepackage{polyglossia}\n"; // set the main language - os << "\\setdefaultlanguage"; + lyxpreamble += "\\setdefaultlanguage"; if (!language->polyglossiaOpts().empty()) - os << "[" << from_ascii(language->polyglossiaOpts()) << "]"; - os << "{" + from_ascii(language->polyglossia()) + "}\n"; - texrow.newline(); + lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]"; + lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n"; // now setup the other languages - std::map const polylangs = + std::map const polylangs = features.getPolyglossiaLanguages(); for (std::map::const_iterator mit = polylangs.begin(); mit != polylangs.end() ; ++mit) { - os << "\\setotherlanguage"; + lyxpreamble += "\\setotherlanguage"; if (!mit->second.empty()) - os << "[" << from_ascii(mit->second) << "]"; - os << "{" << from_ascii(mit->first) << "}\n"; - texrow.newline(); + lyxpreamble += "[" + from_ascii(mit->second) + "]"; + lyxpreamble += "{" + from_ascii(mit->first) + "}\n"; } } + + // Load custom language package here + if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) { + if (lang_package == "default") + lyxpreamble += from_utf8(lyxrc.language_custom_package); + else + lyxpreamble += from_utf8(lang_package); + lyxpreamble += '\n'; + } + + docstring const i18npreamble = + features.getTClassI18nPreamble(use_babel, use_polyglossia); + if (!i18npreamble.empty()) + lyxpreamble += i18npreamble + '\n'; + + os << lyxpreamble; + return use_babel; } @@ -1956,20 +2017,20 @@ bool BufferParams::hasClassDefaults() const DocumentClass const & BufferParams::documentClass() const { - return *doc_class_; + return *doc_class_.get(); } -DocumentClass const * BufferParams::documentClassPtr() const +DocumentClassConstPtr BufferParams::documentClassPtr() const { return doc_class_; } -void BufferParams::setDocumentClass(DocumentClass const * const tc) +void BufferParams::setDocumentClass(DocumentClassConstPtr tc) { // evil, but this function is evil - doc_class_ = const_cast(tc); + doc_class_ = const_pointer_cast(tc); } @@ -1978,7 +2039,7 @@ bool BufferParams::setBaseClass(string const & classname) LYXERR(Debug::TCLASS, "setBaseClass: " << classname); LayoutFileList & bcl = LayoutFileList::get(); if (!bcl.haveClass(classname)) { - docstring s = + docstring s = bformat(_("The layout file:\n" "%1$s\n" "could not be found. A default textclass with default\n" @@ -1991,7 +2052,7 @@ bool BufferParams::setBaseClass(string const & classname) bool const success = bcl[classname].load(); if (!success) { - docstring s = + docstring s = bformat(_("Due to some error in it, the layout file:\n" "%1$s\n" "could not be loaded. A default textclass with default\n" @@ -2003,7 +2064,7 @@ bool BufferParams::setBaseClass(string const & classname) } pimpl_->baseClass_ = classname; - layoutModules_.adaptToBaseClass(baseClass(), removedModules_); + layout_modules_.adaptToBaseClass(baseClass(), removed_modules_); return true; } @@ -2012,7 +2073,7 @@ LayoutFile const * BufferParams::baseClass() const { if (LayoutFileList::get().haveClass(pimpl_->baseClass_)) return &(LayoutFileList::get()[pimpl_->baseClass_]); - else + else return 0; } @@ -2028,10 +2089,23 @@ void BufferParams::makeDocumentClass() if (!baseClass()) return; - doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_)); + LayoutModuleList mods; + 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) + mods.push_back(*it); + + doc_class_ = getDocumentClass(*baseClass(), mods); if (!local_layout.empty()) { - if (!doc_class_->read(local_layout, TextClass::MODULE)) { + TextClass::ReturnValues success = + doc_class_->read(local_layout, TextClass::MODULE); + if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) { docstring const msg = _("Error reading internal layout information"); frontend::Alert::warning(_("Read Error"), msg); } @@ -2039,37 +2113,225 @@ void BufferParams::makeDocumentClass() } -bool BufferParams::moduleCanBeAdded(string const & modName) const +bool BufferParams::layoutModuleCanBeAdded(string const & modName) const { - return layoutModules_.moduleCanBeAdded(modName, baseClass()); + return layout_modules_.moduleCanBeAdded(modName, baseClass()); +} + + +bool BufferParams::citationModuleCanBeAdded(string const & modName) const +{ + return cite_engine_.moduleCanBeAdded(modName, baseClass()); } bool BufferParams::addLayoutModule(string const & modName) { - LayoutModuleList::const_iterator it = layoutModules_.begin(); - LayoutModuleList::const_iterator end = layoutModules_.end(); - for (; it != end; it++) - if (*it == modName) + LayoutModuleList::const_iterator it = layout_modules_.begin(); + LayoutModuleList::const_iterator end = layout_modules_.end(); + for (; it != end; ++it) + if (*it == modName) return false; - layoutModules_.push_back(modName); + layout_modules_.push_back(modName); return true; } +string BufferParams::bufferFormat() const +{ + string format = documentClass().outputFormat(); + if (format == "latex") { + if (useNonTeXFonts) + return "xetex"; + if (encoding().package() == Encoding::japanese) + return "platex"; + } + return format; +} + + +bool BufferParams::isExportable(string const & format) const +{ + vector backs = backends(); + for (vector::const_iterator it = backs.begin(); + it != backs.end(); ++it) + if (theConverters().isReachable(*it, format)) + return true; + return false; +} + + +vector BufferParams::exportableFormats(bool only_viewable) const +{ + vector const backs = backends(); + set excludes; + if (useNonTeXFonts) { + excludes.insert("latex"); + excludes.insert("pdflatex"); + } + vector result = + theConverters().getReachable(backs[0], only_viewable, true, excludes); + for (vector::const_iterator it = backs.begin() + 1; + it != backs.end(); ++it) { + vector r = + theConverters().getReachable(*it, only_viewable, false, excludes); + result.insert(result.end(), r.begin(), r.end()); + } + return result; +} + + +bool BufferParams::isExportableFormat(string const & format) const +{ + typedef vector Formats; + Formats formats; + formats = exportableFormats(true); + Formats::const_iterator fit = formats.begin(); + Formats::const_iterator end = formats.end(); + for (; fit != end ; ++fit) { + if ((*fit)->name() == format) + return true; + } + return false; +} + + +vector BufferParams::backends() const +{ + vector v; + string const buffmt = bufferFormat(); + + // FIXME: Don't hardcode format names here, but use a flag + if (buffmt == "latex") { + if (!useNonTeXFonts) { + v.push_back("pdflatex"); + v.push_back("latex"); + } + v.push_back("luatex"); + v.push_back("dviluatex"); + v.push_back("xetex"); + } else if (buffmt == "xetex") { + v.push_back("xetex"); + // FIXME: need to test all languages (bug 8205) + if (!language || !language->isPolyglossiaExclusive()) { + v.push_back("luatex"); + v.push_back("dviluatex"); + } + } else + v.push_back(buffmt); + + v.push_back("xhtml"); + v.push_back("text"); + v.push_back("lyx"); + return v; +} + + +OutputParams::FLAVOR BufferParams::getOutputFlavor(string const format) const +{ + string const dformat = (format.empty() || format == "default") ? + getDefaultOutputFormat() : format; + DefaultFlavorCache::const_iterator it = + default_flavors_.find(dformat); + + if (it != default_flavors_.end()) + return it->second; + + OutputParams::FLAVOR result = OutputParams::LATEX; + + // FIXME It'd be better not to hardcode this, but to do + // something with formats. + if (dformat == "xhtml") + result = OutputParams::HTML; + else if (dformat == "text") + result = OutputParams::TEXT; + else if (dformat == "lyx") + result = OutputParams::LYX; + else if (dformat == "pdflatex") + result = OutputParams::PDFLATEX; + else if (dformat == "xetex") + result = OutputParams::XETEX; + else if (dformat == "luatex") + result = OutputParams::LUATEX; + else if (dformat == "dviluatex") + result = OutputParams::DVILUATEX; + else { + // Try to determine flavor of default output format + vector backs = backends(); + 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); + if (!p.empty() && (path.empty() || p.size() < path.size())) { + path = p; + } + } + if (!path.empty()) + result = theConverters().getFlavor(path); + } + } + // cache this flavor + default_flavors_[dformat] = result; + return result; +} + + +string BufferParams::getDefaultOutputFormat() const +{ + if (!default_output_format.empty() + && default_output_format != "default") + return default_output_format; + if (isDocBook() + || useNonTeXFonts + || encoding().package() == Encoding::japanese) { + vector const formats = exportableFormats(true); + if (formats.empty()) + return string(); + // return the first we find + return formats.front()->name(); + } + return lyxrc.default_view_format; +} + Font const BufferParams::getFont() const { FontInfo f = documentClass().defaultfont(); - if (fontsDefaultFamily == "rmdefault") + if (fonts_default_family == "rmdefault") f.setFamily(ROMAN_FAMILY); - else if (fontsDefaultFamily == "sfdefault") + else if (fonts_default_family == "sfdefault") f.setFamily(SANS_FAMILY); - else if (fontsDefaultFamily == "ttdefault") + else if (fonts_default_family == "ttdefault") f.setFamily(TYPEWRITER_FAMILY); return Font(f, language); } +InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const qs) const +{ + return quoteslangtranslator().find(qs); +} + + +bool BufferParams::isLatex() const +{ + return documentClass().outputType() == LATEX; +} + + +bool BufferParams::isLiterate() const +{ + return documentClass().outputType() == LITERATE; +} + + +bool BufferParams::isDocBook() const +{ + return documentClass().outputType() == DOCBOOK; +} + + void BufferParams::readPreamble(Lexer & lex) { if (lex.getString() != "\\begin_preamble") @@ -2090,6 +2352,18 @@ void BufferParams::readLocalLayout(Lexer & lex) } +bool BufferParams::setLanguage(string const & lang) +{ + Language const *new_language = languages.getLanguage(lang); + if (!new_language) { + // Language lang was not found + return false; + } + language = new_language; + return true; +} + + void BufferParams::readLanguage(Lexer & lex) { if (!lex.next()) return; @@ -2097,8 +2371,7 @@ void BufferParams::readLanguage(Lexer & lex) string const tmptok = lex.getString(); // check if tmptok is part of tex_babel in tex-defs.h - language = languages.getLanguage(tmptok); - if (!language) { + if (!setLanguage(tmptok)) { // Language tmptok was not found language = default_language; lyxerr << "Warning: Setting language `" @@ -2110,7 +2383,7 @@ void BufferParams::readLanguage(Lexer & lex) void BufferParams::readGraphicsDriver(Lexer & lex) { - if (!lex.next()) + if (!lex.next()) return; string const tmptok = lex.getString(); @@ -2120,14 +2393,14 @@ void BufferParams::readGraphicsDriver(Lexer & lex) string const test = tex_graphics[n++]; if (test == tmptok) { - graphicsDriver = tmptok; + graphics_driver = tmptok; break; } if (test.empty()) { lex.printError( "Warning: graphics driver `$$Token' not recognized!\n" " Setting graphics driver to `default'.\n"); - graphicsDriver = "default"; + graphics_driver = "default"; break; } } @@ -2136,7 +2409,7 @@ void BufferParams::readGraphicsDriver(Lexer & lex) void BufferParams::readBullets(Lexer & lex) { - if (!lex.next()) + if (!lex.next()) return; int const index = lex.getInteger(); @@ -2156,7 +2429,7 @@ void BufferParams::readBullets(Lexer & lex) void BufferParams::readBulletsLaTeX(Lexer & lex) { // The bullet class should be able to read this. - if (!lex.next()) + if (!lex.next()) return; int const index = lex.getInteger(); lex.next(true); @@ -2195,22 +2468,22 @@ void BufferParams::readRemovedModules(Lexer & lex) string mod = lex.getString(); if (mod == "\\end_removed_modules") break; - removedModules_.push_back(mod); + removed_modules_.push_back(mod); lex.eatLine(); } - // now we want to remove any removed modules that were previously - // added. normally, that will be because default modules were added in - // setBaseClass(), which gets called when \textclass is read at the + // now we want to remove any removed modules that were previously + // added. normally, that will be because default modules were added in + // setBaseClass(), which gets called when \textclass is read at the // start of the read. - list::const_iterator rit = removedModules_.begin(); - list::const_iterator const ren = removedModules_.end(); - for (; rit != ren; rit++) { - LayoutModuleList::iterator const mit = layoutModules_.begin(); - LayoutModuleList::iterator const men = layoutModules_.end(); + list::const_iterator rit = removed_modules_.begin(); + list::const_iterator const ren = removed_modules_.end(); + for (; rit != ren; ++rit) { + LayoutModuleList::iterator const mit = layout_modules_.begin(); + LayoutModuleList::iterator const men = layout_modules_.end(); LayoutModuleList::iterator found = find(mit, men, *rit); if (found == men) continue; - layoutModules_.erase(found); + layout_modules_.erase(found); } } @@ -2226,7 +2499,7 @@ void BufferParams::readIncludeonly(Lexer & lex) string child = lex.getString(); if (child == "\\end_includeonly") break; - includedChildren_.push_back(child); + included_children_.push_back(child); lex.eatLine(); } } @@ -2234,11 +2507,7 @@ void BufferParams::readIncludeonly(Lexer & lex) string BufferParams::paperSizeName(PapersizePurpose purpose) const { - char real_papersize = papersize; - if (real_papersize == PAPER_DEFAULT) - real_papersize = lyxrc.default_papersize; - - switch (real_papersize) { + switch (papersize) { case PAPER_DEFAULT: // could be anything, so don't guess return string(); @@ -2384,6 +2653,14 @@ string const BufferParams::dvips_options() const { string result; + // If the class loads the geometry package, we do not know which + // paper size is used, since we do not set it (bug 7013). + // Therefore we must not specify any argument here. + // dvips gets the correct paper size via DVI specials in this case + // (if the class uses the geometry package correctly). + if (documentClass().provides("geometry")) + return result; + if (use_geometry && papersize == PAPER_CUSTOM && !lyxrc.print_paper_dimension_flag.empty() @@ -2419,8 +2696,6 @@ string const BufferParams::font_encoding() const string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const { - if (lyxrc.language_package_selection == LyXRC::LP_CUSTOM) - return lyxrc.language_custom_package; // suppress the babel call if there is no BabelName defined // for the document language in the lib/languages file and if no // other languages are used (lang_opts is then empty) @@ -2440,12 +2715,12 @@ docstring BufferParams::getGraphicsDriver(string const & package) const docstring result; if (package == "geometry") { - if (graphicsDriver == "dvips" - || graphicsDriver == "dvipdfm" - || graphicsDriver == "pdftex" - || graphicsDriver == "vtex") - result = from_ascii(graphicsDriver); - else if (graphicsDriver == "dvipdfmx") + if (graphics_driver == "dvips" + || graphics_driver == "dvipdfm" + || graphics_driver == "pdftex" + || graphics_driver == "vtex") + result = from_ascii(graphics_driver); + else if (graphics_driver == "dvipdfmx") result = from_ascii("dvipdfm"); } @@ -2453,11 +2728,23 @@ docstring BufferParams::getGraphicsDriver(string const & package) const } -void BufferParams::writeEncodingPreamble(odocstream & os, - LaTeXFeatures & features, TexRow & texrow) const +void BufferParams::writeEncodingPreamble(otexstream & os, + LaTeXFeatures & features) const { - if (useXetex) + // XeTeX does not need this + if (features.runparams().flavor == OutputParams::XETEX) + 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"; + } return; + } if (inputenc == "auto") { string const doc_encoding = language->encoding()->latexName(); @@ -2472,9 +2759,6 @@ void BufferParams::writeEncodingPreamble(odocstream & os, // 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 (package == Encoding::japanese) - features.require("japanese"); - if ((!encodings.empty() || package == Encoding::inputenc) && !features.isRequired("japanese")) { os << "\\usepackage["; @@ -2492,7 +2776,6 @@ void BufferParams::writeEncodingPreamble(odocstream & os, os << from_ascii(doc_encoding); } os << "]{inputenc}\n"; - texrow.newline(); } if (package == Encoding::CJK || features.mustProvide("CJK")) { if (language->encoding()->name() == "utf8-cjk" @@ -2500,7 +2783,6 @@ void BufferParams::writeEncodingPreamble(odocstream & os, os << "\\usepackage{CJKutf8}\n"; else os << "\\usepackage{CJK}\n"; - texrow.newline(); } } else if (inputenc != "default") { switch (encoding().package()) { @@ -2511,9 +2793,8 @@ void BufferParams::writeEncodingPreamble(odocstream & os, // do not load inputenc if japanese is used if (features.isRequired("japanese")) break; - os << "\\usepackage[" << from_ascii(inputenc) + os << "\\usepackage[" << from_ascii(encoding().latexName()) << "]{inputenc}\n"; - texrow.newline(); break; case Encoding::CJK: if (encoding().name() == "utf8-cjk" @@ -2521,18 +2802,9 @@ void BufferParams::writeEncodingPreamble(odocstream & os, os << "\\usepackage{CJKutf8}\n"; else os << "\\usepackage{CJK}\n"; - texrow.newline(); break; } } - - // The encoding "armscii8" (for Armenian) is only available when - // the package "armtex" is loaded. - if (language->encoding()->latexName() == "armscii8" - || inputenc == "armscii8") { - os << "\\usepackage{armtex}\n"; - texrow.newline(); - } } @@ -2547,171 +2819,95 @@ string const BufferParams::parseFontName(string const & name) const } -string const BufferParams::loadFonts(string const & rm, - string const & sf, string const & tt, - bool const & sc, bool const & osf, - int const & sfscale, int const & ttscale, - bool const & xetex) const +string const BufferParams::loadFonts(LaTeXFeatures & features) const { - /* The LaTeX font world is in a flux. In the PSNFSS font interface, - several packages have been replaced by others, that might not - be installed on every system. We have to take care for that - (see psnfss.pdf). We try to support all psnfss fonts as well - as the fonts that have become de facto standard in the LaTeX - world (e.g. Latin Modern). We do not support obsolete fonts - (like PSLatex). In general, it should be possible to mix any - rm font with any sf or tt font, respectively. (JSpitzm) - TODO: - -- separate math fonts. - */ - - if (rm == "default" && sf == "default" && tt == "default") + if (fonts_roman == "default" && fonts_sans == "default" + && fonts_typewriter == "default" + && (fonts_math == "default" || fonts_math == "auto")) //nothing to do return string(); ostringstream os; - if (xetex) { - if (rm != "default") { - os << "\\setmainfont[Mapping=tex-text"; - if (osf) + /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle + * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/ + * Mapping=tex-text option assures TeX ligatures (such as "--") + * are resolved. Note that tt does not use these ligatures. + * TODO: + * -- add more GUI options? + * -- add more fonts (fonts for other scripts) + * -- if there's a way to find out if a font really supports + * OldStyle, enable/disable the widget accordingly. + */ + if (useNonTeXFonts && features.isAvailable("fontspec")) { + // "Mapping=tex-text" and "Ligatures=TeX" are equivalent. + // However, until v.2 (2010/07/11) fontspec only knew + // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX" + // was introduced for both XeTeX and LuaTeX (LuaTeX + // didn't understand "Mapping=tex-text", while XeTeX + // understood both. With most recent versions, both + // 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) + string const texmapping = + (features.runparams().flavor == OutputParams::XETEX) ? + "Mapping=tex-text" : "Ligatures=TeX"; + if (fonts_roman != "default") { + os << "\\setmainfont[" << texmapping; + if (fonts_old_figures) os << ",Numbers=OldStyle"; - os << "]{" << parseFontName(rm) << "}\n"; + os << "]{" << parseFontName(fonts_roman) << "}\n"; } - if (sf != "default") { - string const sans = parseFontName(sf); - if (sfscale != 100) - os << "\\setsansfont[Scale=" - << float(sfscale) / 100 - << ",Mapping=tex-text]{" + if (fonts_sans != "default") { + string const sans = parseFontName(fonts_sans); + if (fonts_sans_scale != 100) + os << "\\setsansfont[Scale=" + << float(fonts_sans_scale) / 100 + << "," << texmapping << "]{" << sans << "}\n"; else - os << "\\setsansfont[Mapping=tex-text]{" + os << "\\setsansfont[" << texmapping << "]{" << sans << "}\n"; } - if (tt != "default") { - string const mono = parseFontName(tt); - if (ttscale != 100) - os << "\\setmonofont[Scale=" - << float(sfscale) / 100 + if (fonts_typewriter != "default") { + string const mono = parseFontName(fonts_typewriter); + if (fonts_typewriter_scale != 100) + os << "\\setmonofont[Scale=" + << float(fonts_typewriter_scale) / 100 << "]{" << mono << "}\n"; else - os << "\\setmonofont[Mapping=tex-text]{" + os << "\\setmonofont{" << mono << "}\n"; } return os.str(); } + // Tex Fonts + bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1"); + bool const dryrun = features.runparams().dryrun; + bool const complete = (fonts_sans == "default" && fonts_typewriter == "default"); + bool const nomath = (fonts_math == "default"); + // ROMAN FONTS - // Computer Modern (must be explicitly selectable -- there might be classes - // that define a different default font! - if (rm == "cmr") { - os << "\\renewcommand{\\rmdefault}{cmr}\n"; - // osf for Computer Modern needs eco.sty - if (osf) - os << "\\usepackage{eco}\n"; - } - // Latin Modern Roman - else if (rm == "lmodern") - os << "\\usepackage{lmodern}\n"; - // AE - else if (rm == "ae") { - // not needed when using OT1 font encoding. - if (font_encoding() != "default") - os << "\\usepackage{ae,aecompl}\n"; - } - // Times - else if (rm == "times") { - // try to load the best available package - if (LaTeXFeatures::isAvailable("mathptmx")) - os << "\\usepackage{mathptmx}\n"; - else if (LaTeXFeatures::isAvailable("mathptm")) - os << "\\usepackage{mathptm}\n"; - else - os << "\\usepackage{times}\n"; - } - // Palatino - else if (rm == "palatino") { - // try to load the best available package - if (LaTeXFeatures::isAvailable("mathpazo")) { - os << "\\usepackage"; - if (osf || sc) { - os << '['; - if (!osf) - os << "sc"; - else - // "osf" includes "sc"! - os << "osf"; - os << ']'; - } - os << "{mathpazo}\n"; - } - else if (LaTeXFeatures::isAvailable("mathpple")) - os << "\\usepackage{mathpple}\n"; - else - os << "\\usepackage{palatino}\n"; - } - // Utopia - else if (rm == "utopia") { - // fourier supersedes utopia.sty, but does - // not work with OT1 encoding. - if (LaTeXFeatures::isAvailable("fourier") - && font_encoding() != "default") { - os << "\\usepackage"; - if (osf || sc) { - os << '['; - if (sc) - os << "expert"; - if (osf && sc) - os << ','; - if (osf) - os << "oldstyle"; - os << ']'; - } - os << "{fourier}\n"; - } - else - os << "\\usepackage{utopia}\n"; - } - // Bera (complete fontset) - else if (rm == "bera" && sf == "default" && tt == "default") - os << "\\usepackage{bera}\n"; - // everything else - else if (rm != "default") - os << "\\usepackage" << "{" << rm << "}\n"; + os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_roman)).getLaTeXCode( + dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures, + nomath); // SANS SERIF - // Helvetica, Bera Sans - if (sf == "helvet" || sf == "berasans") { - if (sfscale != 100) - os << "\\usepackage[scaled=" << float(sfscale) / 100 - << "]{" << sf << "}\n"; - else - os << "\\usepackage{" << sf << "}\n"; - } - // Avant Garde - else if (sf == "avant") - os << "\\usepackage{" << sf << "}\n"; - // Computer Modern, Latin Modern, CM Bright - else if (sf != "default") - os << "\\renewcommand{\\sfdefault}{" << sf << "}\n"; - - // monospaced/typewriter - // Courier, LuxiMono - if (tt == "luximono" || tt == "beramono") { - if (ttscale != 100) - os << "\\usepackage[scaled=" << float(ttscale) / 100 - << "]{" << tt << "}\n"; - else - os << "\\usepackage{" << tt << "}\n"; - } - // Courier - else if (tt == "courier" ) - os << "\\usepackage{" << tt << "}\n"; - // Computer Modern, Latin Modern, CM Bright - else if (tt != "default") - os << "\\renewcommand{\\ttdefault}{" << tt << "}\n"; + os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_sans)).getLaTeXCode( + dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures, + nomath, fonts_sans_scale); + + // MONOSPACED/TYPEWRITER + os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_typewriter)).getLaTeXCode( + dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures, + nomath, fonts_typewriter_scale); + + // MATH + os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getLaTeXCode( + dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures, + nomath); return os.str(); } @@ -2719,11 +2915,15 @@ string const BufferParams::loadFonts(string const & rm, Encoding const & BufferParams::encoding() const { - if (useXetex) - return *(encodings.fromLaTeXName("utf8-plain")); + // 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. + if (useNonTeXFonts) + return *(encodings.fromLyXName("utf8-plain")); if (inputenc == "auto" || inputenc == "default") return *language->encoding(); - Encoding const * const enc = encodings.fromLaTeXName(inputenc); + Encoding const * const enc = encodings.fromLyXName(inputenc); if (enc) return *enc; LYXERR0("Unknown inputenc value `" << inputenc @@ -2732,20 +2932,75 @@ Encoding const & BufferParams::encoding() const } -CiteEngine BufferParams::citeEngine() 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 +{ + return documentClass().defaultBiblioStyle(); +} + + +bool const & BufferParams::fullAuthorList() const +{ + return documentClass().fullAuthorList(); +} + + +void BufferParams::setCiteEngine(string const & engine) +{ + clearCiteEngine(); + addCiteEngine(engine); +} + + +void BufferParams::setCiteEngine(vector const & engine) +{ + clearCiteEngine(); + addCiteEngine(engine); +} + + +vector BufferParams::citeCommands() const { - // FIXME the class should provide the numerical/ - // authoryear choice - if (documentClass().provides("natbib") - && cite_engine_ != ENGINE_NATBIB_NUMERICAL) - return ENGINE_NATBIB_AUTHORYEAR; - return cite_engine_; + static CitationStyle const default_style; + vector commands = + documentClass().citeCommands(citeEngineType()); + if (commands.empty()) + commands.push_back(default_style.cmd); + return commands; } -void BufferParams::setCiteEngine(CiteEngine cite_engine) +vector BufferParams::citeStyles() const { - cite_engine_ = cite_engine; + static CitationStyle const default_style; + vector styles = + documentClass().citeStyles(citeEngineType()); + if (styles.empty()) + styles.push_back(default_style); + return styles; } } // namespace lyx