X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferParams.cpp;h=24613e5bf835d1d3d5c891149e0915e99a8ea120;hb=b64d17e9dcaeb84a94095622c93a051e4d93eab7;hp=21b8237fd29f0eb31051da596e4c2db9e31afb8f;hpb=c6648aaeb9d9b870aa65a48fe649388198a0f5bd;p=lyx.git diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp index 21b8237fd2..24613e5bf8 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; } @@ -360,11 +360,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; @@ -395,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; @@ -414,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; @@ -427,6 +427,38 @@ docstring BufferParams::B_(string const & l10n) const } +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; +} + + +vector const & BufferParams::auto_packages() +{ + static vector packages; + if (packages.empty()) { + // adding a package here implies a file format change! + packages.push_back("amsmath"); + packages.push_back("amssymb"); + packages.push_back("esint"); + packages.push_back("mathdots"); + packages.push_back("mathtools"); + packages.push_back("mhchem"); + packages.push_back("undertilde"); + } + return packages; +} + + AuthorList & BufferParams::authors() { return pimpl_->authorlist; @@ -548,7 +580,7 @@ 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(); @@ -558,12 +590,12 @@ string BufferParams::readToken(Lexer & lex, string const & token, 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" @@ -600,6 +632,8 @@ 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") { @@ -668,26 +702,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") { @@ -850,6 +881,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") { @@ -865,7 +898,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; } @@ -897,20 +930,20 @@ 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 (!removed_modules_.empty()) { os << "\\begin_removed_modules" << '\n'; list::const_iterator it = removed_modules_.begin(); list::const_iterator en = removed_modules_.end(); - for (; it != en; it++) + for (; it != en; ++it) os << *it << '\n'; os << "\\end_removed_modules" << '\n'; } @@ -920,7 +953,7 @@ void BufferParams::writeFile(ostream & os) const os << "\\begin_modules" << '\n'; LayoutModuleList::const_iterator it = layout_modules_.begin(); LayoutModuleList::const_iterator en = layout_modules_.end(); - for (; it != en; it++) + for (; it != en; ++it) os << *it << '\n'; os << "\\end_modules" << '\n'; } @@ -930,7 +963,7 @@ void BufferParams::writeFile(ostream & os) const os << "\\begin_includeonly" << '\n'; list::const_iterator it = included_children_.begin(); list::const_iterator en = included_children_.end(); - for (; it != en; it++) + for (; it != en; ++it) os << *it << '\n'; os << "\\end_includeonly" << '\n'; } @@ -939,7 +972,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 @@ -965,7 +998,7 @@ void BufferParams::writeFile(ostream & os) const if (!fonts_cjk.empty()) { os << "\\font_cjk " << fonts_cjk << '\n'; } - os << "\n\\graphics " << graphics_driver << '\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()) @@ -982,17 +1015,34 @@ 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); + vector const & packages = auto_packages(); + for (size_t i = 0; i < packages.size(); ++i) + os << "\n\\use_package " << packages[i] << ' ' + << use_package(packages[i]); + + 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'; @@ -1052,7 +1102,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 @@ -1088,10 +1138,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()) @@ -1114,6 +1165,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"); @@ -1133,7 +1185,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"); } @@ -1147,16 +1199,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 || + documentClass().provides("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()) @@ -1165,7 +1217,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) { @@ -1193,14 +1245,14 @@ void BufferParams::validate(LaTeXFeatures & features) const features.require("color"); } + // some languages are only available via polyglossia if (features.runparams().flavor == OutputParams::XETEX - && useNonTeXFonts) + && (features.hasPolyglossiaExclusiveLanguages() + || useNonTeXFonts)) features.require("polyglossia"); - if (language->lang() == "vietnamese") - features.require("vietnamese"); - else if (language->lang() == "japanese") - features.require("japanese"); + if (!language->requires().empty()) + features.require(language->requires()); } @@ -1210,7 +1262,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, // 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 to load any other package before the document class, unless you + // 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")) @@ -1324,13 +1376,14 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, 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() << ','; } @@ -1368,7 +1421,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, fonts_sans_scale, fonts_typewriter_scale, useNonTeXFonts, features); if (!fonts.empty()) - os << from_ascii(fonts); + os << from_utf8(fonts); if (fonts_default_family != "default") os << "\\renewcommand{\\familydefault}{\\" @@ -1409,7 +1462,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, 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()) { @@ -1427,7 +1480,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, 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); @@ -1546,59 +1599,8 @@ bool BufferParams::writeLaTeX(otexstream & 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 - break; - 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"; @@ -1641,7 +1643,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, 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"); } @@ -1650,7 +1652,7 @@ bool BufferParams::writeLaTeX(otexstream & 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"); } @@ -1703,6 +1705,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, // Now insert the LyX specific LaTeX commands... docstring lyxpreamble; + features.resolveAlternatives(); if (output_sync) { if (!output_sync_macro.empty()) @@ -1720,7 +1723,7 @@ bool BufferParams::writeLaTeX(otexstream & 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 (use_babel && (features.isRequired("jurabib") @@ -1742,10 +1745,21 @@ 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)); + } lyxpreamble += "\\newindex["; - lyxpreamble += iit->index(); + lyxpreamble += indexname_latex.first; lyxpreamble += "]{"; - lyxpreamble += iit->shortcut(); + lyxpreamble += escape(iit->shortcut()); lyxpreamble += "}\n"; } } @@ -1763,7 +1777,7 @@ bool BufferParams::writeLaTeX(otexstream & 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; @@ -1780,6 +1794,11 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, // 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; @@ -1894,7 +1913,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, 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) { @@ -1905,6 +1924,15 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, } } + // 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()) @@ -1947,20 +1975,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); } @@ -1969,7 +1997,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" @@ -1982,7 +2010,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 +2031,7 @@ LayoutFile const * BufferParams::baseClass() const { if (LayoutFileList::get().haveClass(pimpl_->baseClass_)) return &(LayoutFileList::get()[pimpl_->baseClass_]); - else + else return 0; } @@ -2019,10 +2047,24 @@ void BufferParams::makeDocumentClass() if (!baseClass()) return; - doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layout_modules_)); + LayoutModuleList mods; + LayoutModuleList::iterator it; + LayoutModuleList::iterator en; + + it = layout_modules_.begin(); + 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); } @@ -2032,7 +2074,8 @@ void BufferParams::makeDocumentClass() bool BufferParams::moduleCanBeAdded(string const & modName) const { - return layout_modules_.moduleCanBeAdded(modName, baseClass()); + return cite_engine_.moduleCanBeAdded(modName, baseClass()) && + layout_modules_.moduleCanBeAdded(modName, baseClass()); } @@ -2040,14 +2083,177 @@ bool BufferParams::addLayoutModule(string const & modName) { LayoutModuleList::const_iterator it = layout_modules_.begin(); LayoutModuleList::const_iterator end = layout_modules_.end(); - for (; it != end; it++) - if (*it == modName) + for (; it != end; ++it) + if (*it == modName) return false; 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; +} + + +namespace { +bool formatSorter(Format const * lhs, Format const * rhs) { + return _(lhs->prettyname()) < _(rhs->prettyname()); +} +} + + +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()); + } + sort(result.begin(), result.end(), formatSorter); + 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"); + 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(); @@ -2061,6 +2267,30 @@ Font const BufferParams::getFont() const } +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") @@ -2081,6 +2311,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; @@ -2088,8 +2330,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 `" @@ -2101,7 +2342,7 @@ void BufferParams::readLanguage(Lexer & lex) void BufferParams::readGraphicsDriver(Lexer & lex) { - if (!lex.next()) + if (!lex.next()) return; string const tmptok = lex.getString(); @@ -2127,7 +2368,7 @@ void BufferParams::readGraphicsDriver(Lexer & lex) void BufferParams::readBullets(Lexer & lex) { - if (!lex.next()) + if (!lex.next()) return; int const index = lex.getInteger(); @@ -2147,7 +2388,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); @@ -2189,13 +2430,13 @@ void BufferParams::readRemovedModules(Lexer & lex) 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 = removed_modules_.begin(); list::const_iterator const ren = removed_modules_.end(); - for (; rit != ren; rit++) { + 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); @@ -2225,11 +2466,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(); @@ -2375,6 +2612,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() @@ -2410,11 +2655,6 @@ string const BufferParams::font_encoding() const string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const { - if (lang_package != "auto" && lang_package != "babel" - && lang_package != "default" && lang_package != "none") - return lang_package; - 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) @@ -2455,7 +2695,8 @@ void BufferParams::writeEncodingPreamble(otexstream & os, return; // LuaTeX neither, but with tex fonts, we need to load // the luainputenc package. - if (features.runparams().flavor == OutputParams::LUATEX) { + 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))) { @@ -2477,9 +2718,6 @@ void BufferParams::writeEncodingPreamble(otexstream & 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["; @@ -2526,12 +2764,6 @@ void BufferParams::writeEncodingPreamble(otexstream & os, 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"; } @@ -2553,17 +2785,7 @@ string const BufferParams::loadFonts(string const & rm, bool const & use_systemfonts, 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. - */ + // TODO: separate math fonts. if (rm == "default" && sf == "default" && tt == "default") //nothing to do @@ -2579,7 +2801,7 @@ string const BufferParams::loadFonts(string const & rm, * -- 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. + * OldStyle, enable/disable the widget accordingly. */ if (use_systemfonts && features.isAvailable("fontspec")) { // "Mapping=tex-text" and "Ligatures=TeX" are equivalent. @@ -2589,7 +2811,8 @@ string const BufferParams::loadFonts(string const & rm, // 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. + // 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"; @@ -2602,8 +2825,8 @@ string const BufferParams::loadFonts(string const & rm, if (sf != "default") { string const sans = parseFontName(sf); if (sfscale != 100) - os << "\\setsansfont[Scale=" - << float(sfscale) / 100 + os << "\\setsansfont[Scale=" + << float(sfscale) / 100 << "," << texmapping << "]{" << sans << "}\n"; else @@ -2613,8 +2836,8 @@ string const BufferParams::loadFonts(string const & rm, if (tt != "default") { string const mono = parseFontName(tt); if (ttscale != 100) - os << "\\setmonofont[Scale=" - << float(ttscale) / 100 + os << "\\setmonofont[Scale=" + << float(ttscale) / 100 << "]{" << mono << "}\n"; else @@ -2624,115 +2847,19 @@ string const BufferParams::loadFonts(string const & rm, return os.str(); } + // Tex Fonts + bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1"); + bool const dryrun = features.runparams().dryrun; + bool const complete = (sf == "default" && tt == "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(rm)).getLaTeXCode(dryrun, ot1, complete, sc, osf); // 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(sf)).getLaTeXCode(dryrun, ot1, complete, sc, osf, sfscale); + + // MONOSPACED/TYPEWRITER + os << theLaTeXFonts().getLaTeXFont(from_ascii(tt)).getLaTeXCode(dryrun, ot1, complete, sc, osf, ttscale); return os.str(); } @@ -2757,20 +2884,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