2 * \file BufferParams.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alfredo Braunstein
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
11 * \author Martin Vermeer
13 * Full author contact details are available in file CREDITS.
18 #include "BufferParams.h"
21 #include "BranchList.h"
22 #include "buffer_funcs.h"
27 #include "LaTeXFeatures.h"
28 #include "ModuleList.h"
32 #include "TextClassList.h"
33 #include "OutputParams.h"
37 #include "PDFOptions.h"
39 #include "frontends/alert.h"
41 #include "insets/InsetListingsParams.h"
43 #include "support/convert.h"
44 #include "support/debug.h"
45 #include "support/docstream.h"
46 #include "support/FileName.h"
47 #include "support/filetools.h"
48 #include "support/gettext.h"
49 #include "support/Messages.h"
50 #include "support/Translator.h"
51 #include "support/lstrings.h"
57 using namespace lyx::support;
60 static char const * const string_paragraph_separation[] = {
65 static char const * const string_quotes_language[] = {
66 "english", "swedish", "german", "polish", "french", "danish", ""
70 static char const * const string_papersize[] = {
71 "default", "custom", "letterpaper", "executivepaper", "legalpaper",
72 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
76 static char const * const string_orientation[] = {
77 "portrait", "landscape", ""
81 static char const * const string_footnotekinds[] = {
82 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
86 static char const * const tex_graphics[] = {
87 "default", "dvips", "dvitops", "emtex",
88 "ln", "oztex", "textures", "none", ""
97 // Paragraph separation
98 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
101 ParSepTranslator const init_parseptranslator()
103 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
104 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
109 ParSepTranslator const & parseptranslator()
111 static ParSepTranslator translator = init_parseptranslator();
117 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
120 QuotesLangTranslator const init_quoteslangtranslator()
122 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
123 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
124 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
125 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
126 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
127 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
132 QuotesLangTranslator const & quoteslangtranslator()
134 static QuotesLangTranslator translator = init_quoteslangtranslator();
140 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
143 PaperSizeTranslator const init_papersizetranslator()
145 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
146 translator.addPair(string_papersize[1], PAPER_CUSTOM);
147 translator.addPair(string_papersize[2], PAPER_USLETTER);
148 translator.addPair(string_papersize[3], PAPER_USLEGAL);
149 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
150 translator.addPair(string_papersize[5], PAPER_A3);
151 translator.addPair(string_papersize[6], PAPER_A4);
152 translator.addPair(string_papersize[7], PAPER_A5);
153 translator.addPair(string_papersize[8], PAPER_B3);
154 translator.addPair(string_papersize[9], PAPER_B4);
155 translator.addPair(string_papersize[10], PAPER_B5);
160 PaperSizeTranslator const & papersizetranslator()
162 static PaperSizeTranslator translator = init_papersizetranslator();
168 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
171 PaperOrientationTranslator const init_paperorientationtranslator()
173 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
174 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
179 PaperOrientationTranslator const & paperorientationtranslator()
181 static PaperOrientationTranslator translator = init_paperorientationtranslator();
187 typedef Translator<int, PageSides> SidesTranslator;
190 SidesTranslator const init_sidestranslator()
192 SidesTranslator translator(1, OneSide);
193 translator.addPair(2, TwoSides);
198 SidesTranslator const & sidestranslator()
200 static SidesTranslator translator = init_sidestranslator();
206 typedef Translator<int, BufferParams::Package> PackageTranslator;
209 PackageTranslator const init_packagetranslator()
211 PackageTranslator translator(0, BufferParams::package_off);
212 translator.addPair(1, BufferParams::package_auto);
213 translator.addPair(2, BufferParams::package_on);
218 PackageTranslator const & packagetranslator()
220 static PackageTranslator translator = init_packagetranslator();
226 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
229 CiteEngineTranslator const init_citeenginetranslator()
231 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
232 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
233 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
234 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
239 CiteEngineTranslator const & citeenginetranslator()
241 static CiteEngineTranslator translator = init_citeenginetranslator();
247 typedef Translator<string, Spacing::Space> SpaceTranslator;
250 SpaceTranslator const init_spacetranslator()
252 SpaceTranslator translator("default", Spacing::Default);
253 translator.addPair("single", Spacing::Single);
254 translator.addPair("onehalf", Spacing::Onehalf);
255 translator.addPair("double", Spacing::Double);
256 translator.addPair("other", Spacing::Other);
261 SpaceTranslator const & spacetranslator()
263 static SpaceTranslator translator = init_spacetranslator();
271 class BufferParams::Impl
276 AuthorList authorlist;
277 BranchList branchlist;
278 Bullet temp_bullets[4];
279 Bullet user_defined_bullets[4];
281 /** This is the amount of space used for paragraph_separation "skip",
282 * and for detached paragraphs in "indented" documents.
285 PDFOptions pdfoptions;
289 BufferParams::Impl::Impl()
290 : defskip(VSpace::MEDSKIP)
292 // set initial author
294 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
299 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
303 return new BufferParams::Impl(*ptr);
307 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
313 BufferParams::BufferParams()
316 setBaseClass(defaultTextclass());
318 paragraph_separation = PARSEP_INDENT;
319 quotes_language = InsetQuotes::EnglishQ;
320 fontsize = "default";
323 papersize = PAPER_DEFAULT;
324 orientation = ORIENTATION_PORTRAIT;
325 use_geometry = false;
326 use_amsmath = package_auto;
327 use_esint = package_auto;
328 cite_engine_ = biblio::ENGINE_BASIC;
329 use_bibtopic = false;
330 trackChanges = false;
331 outputChanges = false;
334 language = default_language;
335 fontsRoman = "default";
336 fontsSans = "default";
337 fontsTypewriter = "default";
338 fontsDefaultFamily = "default";
341 fontsSansScale = 100;
342 fontsTypewriterScale = 100;
344 graphicsDriver = "default";
347 listings_params = string();
348 pagestyle = "default";
351 for (int iter = 0; iter < 4; ++iter) {
352 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
353 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
358 BufferParams::~BufferParams()
362 docstring const BufferParams::B_(string const & l10n) const
364 BOOST_ASSERT(language);
365 return getMessages(language->code()).get(l10n);
369 AuthorList & BufferParams::authors()
371 return pimpl_->authorlist;
375 AuthorList const & BufferParams::authors() const
377 return pimpl_->authorlist;
381 BranchList & BufferParams::branchlist()
383 return pimpl_->branchlist;
387 BranchList const & BufferParams::branchlist() const
389 return pimpl_->branchlist;
393 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
395 BOOST_ASSERT(index < 4);
396 return pimpl_->temp_bullets[index];
400 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
402 BOOST_ASSERT(index < 4);
403 return pimpl_->temp_bullets[index];
407 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
409 BOOST_ASSERT(index < 4);
410 return pimpl_->user_defined_bullets[index];
414 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
416 BOOST_ASSERT(index < 4);
417 return pimpl_->user_defined_bullets[index];
421 Spacing & BufferParams::spacing()
423 return pimpl_->spacing;
427 Spacing const & BufferParams::spacing() const
429 return pimpl_->spacing;
433 PDFOptions & BufferParams::pdfoptions()
435 return pimpl_->pdfoptions;
439 PDFOptions const & BufferParams::pdfoptions() const
441 return pimpl_->pdfoptions;
445 VSpace const & BufferParams::getDefSkip() const
447 return pimpl_->defskip;
451 void BufferParams::setDefSkip(VSpace const & vs)
453 pimpl_->defskip = vs;
457 string const BufferParams::readToken(Lexer & lex, string const & token,
458 FileName const & filepath)
460 if (token == "\\textclass") {
462 string const classname = lex.getString();
463 // if there exists a local layout file, ignore the system one
464 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
465 pair<bool, lyx::textclass_type> pp =
466 make_pair(false, textclass_type(0));
467 if (!filepath.empty())
468 pp = textclasslist.addTextClass(
469 classname, filepath.absFilename());
471 setBaseClass(pp.second);
473 pp = textclasslist.numberOfClass(classname);
475 setBaseClass(pp.second);
477 // a warning will be given for unknown class
478 setBaseClass(defaultTextclass());
482 // FIXME: this warning will be given even if there exists a local .cls
483 // file. Even worse, the .lyx file can not be compiled or exported
484 // because the textclass is marked as unavilable.
485 if (!getTextClass().isTeXClassAvailable()) {
486 docstring const msg =
487 bformat(_("The layout file requested by this document,\n"
489 "is not usable. This is probably because a LaTeX\n"
490 "class or style file required by it is not\n"
491 "available. See the Customization documentation\n"
492 "for more information.\n"), from_utf8(classname));
493 frontend::Alert::warning(_("Document class not available"),
494 msg + _("LyX will not be able to produce output."));
497 } else if (token == "\\begin_preamble") {
499 } else if (token == "\\begin_modules") {
501 } else if (token == "\\options") {
503 options = lex.getString();
504 } else if (token == "\\language") {
506 } else if (token == "\\inputencoding") {
508 } else if (token == "\\graphics") {
509 readGraphicsDriver(lex);
510 } else if (token == "\\font_roman") {
512 } else if (token == "\\font_sans") {
514 } else if (token == "\\font_typewriter") {
515 lex >> fontsTypewriter;
516 } else if (token == "\\font_default_family") {
517 lex >> fontsDefaultFamily;
518 } else if (token == "\\font_sc") {
520 } else if (token == "\\font_osf") {
522 } else if (token == "\\font_sf_scale") {
523 lex >> fontsSansScale;
524 } else if (token == "\\font_tt_scale") {
525 lex >> fontsTypewriterScale;
526 } else if (token == "\\paragraph_separation") {
529 paragraph_separation = parseptranslator().find(parsep);
530 } else if (token == "\\defskip") {
532 pimpl_->defskip = VSpace(lex.getString());
533 } else if (token == "\\quotes_language") {
536 quotes_language = quoteslangtranslator().find(quotes_lang);
537 } else if (token == "\\papersize") {
540 papersize = papersizetranslator().find(ppsize);
541 } else if (token == "\\use_geometry") {
543 } else if (token == "\\use_amsmath") {
546 use_amsmath = packagetranslator().find(use_ams);
547 } else if (token == "\\use_esint") {
550 use_esint = packagetranslator().find(useesint);
551 } else if (token == "\\cite_engine") {
554 cite_engine_ = citeenginetranslator().find(engine);
555 } else if (token == "\\use_bibtopic") {
557 } else if (token == "\\tracking_changes") {
559 } else if (token == "\\output_changes") {
560 lex >> outputChanges;
561 } else if (token == "\\branch") {
563 docstring branch = lex.getDocString();
564 branchlist().add(branch);
567 string const tok = lex.getString();
568 if (tok == "\\end_branch")
570 Branch * branch_ptr = branchlist().find(branch);
571 if (tok == "\\selected") {
574 branch_ptr->setSelected(lex.getInteger());
576 // not yet operational
577 if (tok == "\\color") {
579 string color = lex.getString();
581 branch_ptr->setColor(color);
582 // Update also the Color table:
584 color = lcolor.getX11Name(Color_background);
586 lcolor.setColor(to_utf8(branch), color);
590 } else if (token == "\\author") {
592 istringstream ss(lex.getString());
595 author_map.push_back(pimpl_->authorlist.record(a));
596 } else if (token == "\\paperorientation") {
599 orientation = paperorientationtranslator().find(orient);
600 } else if (token == "\\paperwidth") {
602 } else if (token == "\\paperheight") {
604 } else if (token == "\\leftmargin") {
606 } else if (token == "\\topmargin") {
608 } else if (token == "\\rightmargin") {
610 } else if (token == "\\bottommargin") {
612 } else if (token == "\\headheight") {
614 } else if (token == "\\headsep") {
616 } else if (token == "\\footskip") {
618 } else if (token == "\\paperfontsize") {
620 } else if (token == "\\papercolumns") {
622 } else if (token == "\\listings_params") {
625 listings_params = InsetListingsParams(par).params();
626 } else if (token == "\\papersides") {
629 sides = sidestranslator().find(psides);
630 } else if (token == "\\paperpagestyle") {
632 } else if (token == "\\bullet") {
634 } else if (token == "\\bulletLaTeX") {
635 readBulletsLaTeX(lex);
636 } else if (token == "\\secnumdepth") {
638 } else if (token == "\\tocdepth") {
640 } else if (token == "\\spacing") {
644 if (nspacing == "other") {
647 spacing().set(spacetranslator().find(nspacing), tmp_val);
648 } else if (token == "\\float_placement") {
649 lex >> float_placement;
651 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
652 string toktmp = pdfoptions().readToken(lex, token);
653 if (!toktmp.empty()) {
654 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
659 lyxerr << "BufferParams::readToken(): Unknown token: " <<
668 void BufferParams::writeFile(ostream & os) const
670 // The top of the file is written by the buffer.
671 // Prints out the buffer info into the .lyx file given by file
674 os << "\\textclass " << textclasslist[baseClass_].name() << '\n';
677 if (!preamble.empty()) {
678 // remove '\n' from the end of preamble
679 string const tmppreamble = rtrim(preamble, "\n");
680 os << "\\begin_preamble\n"
682 << "\n\\end_preamble\n";
686 if (!options.empty()) {
687 os << "\\options " << options << '\n';
691 if (!layoutModules_.empty()) {
692 os << "\\begin_modules" << '\n';
693 LayoutModuleList::const_iterator it = layoutModules_.begin();
694 for (; it != layoutModules_.end(); it++)
696 os << "\\end_modules" << '\n';
699 // then the text parameters
700 if (language != ignore_language)
701 os << "\\language " << language->lang() << '\n';
702 os << "\\inputencoding " << inputenc
703 << "\n\\font_roman " << fontsRoman
704 << "\n\\font_sans " << fontsSans
705 << "\n\\font_typewriter " << fontsTypewriter
706 << "\n\\font_default_family " << fontsDefaultFamily
707 << "\n\\font_sc " << convert<string>(fontsSC)
708 << "\n\\font_osf " << convert<string>(fontsOSF)
709 << "\n\\font_sf_scale " << fontsSansScale
710 << "\n\\font_tt_scale " << fontsTypewriterScale
711 << "\n\\graphics " << graphicsDriver << '\n';
713 if (!float_placement.empty()) {
714 os << "\\float_placement " << float_placement << '\n';
716 os << "\\paperfontsize " << fontsize << '\n';
718 spacing().writeFile(os);
719 pdfoptions().writeFile(os);
721 os << "\\papersize " << string_papersize[papersize]
722 << "\n\\use_geometry " << convert<string>(use_geometry)
723 << "\n\\use_amsmath " << use_amsmath
724 << "\n\\use_esint " << use_esint
725 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
726 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
727 << "\n\\paperorientation " << string_orientation[orientation]
730 BranchList::const_iterator it = branchlist().begin();
731 BranchList::const_iterator end = branchlist().end();
732 for (; it != end; ++it) {
733 os << "\\branch " << to_utf8(it->getBranch())
734 << "\n\\selected " << it->getSelected()
735 << "\n\\color " << lyx::X11hexname(it->getColor())
740 if (!paperwidth.empty())
741 os << "\\paperwidth "
742 << VSpace(paperwidth).asLyXCommand() << '\n';
743 if (!paperheight.empty())
744 os << "\\paperheight "
745 << VSpace(paperheight).asLyXCommand() << '\n';
746 if (!leftmargin.empty())
747 os << "\\leftmargin "
748 << VSpace(leftmargin).asLyXCommand() << '\n';
749 if (!topmargin.empty())
751 << VSpace(topmargin).asLyXCommand() << '\n';
752 if (!rightmargin.empty())
753 os << "\\rightmargin "
754 << VSpace(rightmargin).asLyXCommand() << '\n';
755 if (!bottommargin.empty())
756 os << "\\bottommargin "
757 << VSpace(bottommargin).asLyXCommand() << '\n';
758 if (!headheight.empty())
759 os << "\\headheight "
760 << VSpace(headheight).asLyXCommand() << '\n';
761 if (!headsep.empty())
763 << VSpace(headsep).asLyXCommand() << '\n';
764 if (!footskip.empty())
766 << VSpace(footskip).asLyXCommand() << '\n';
767 os << "\\secnumdepth " << secnumdepth
768 << "\n\\tocdepth " << tocdepth
769 << "\n\\paragraph_separation "
770 << string_paragraph_separation[paragraph_separation]
771 << "\n\\defskip " << getDefSkip().asLyXCommand()
772 << "\n\\quotes_language "
773 << string_quotes_language[quotes_language]
774 << "\n\\papercolumns " << columns
775 << "\n\\papersides " << sides
776 << "\n\\paperpagestyle " << pagestyle << '\n';
777 if (!listings_params.empty())
778 os << "\\listings_params \"" <<
779 InsetListingsParams(listings_params).encodedString() << "\"\n";
780 for (int i = 0; i < 4; ++i) {
781 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
782 if (user_defined_bullet(i).getFont() != -1) {
783 os << "\\bullet " << i << " "
784 << user_defined_bullet(i).getFont() << " "
785 << user_defined_bullet(i).getCharacter() << " "
786 << user_defined_bullet(i).getSize() << "\n";
790 os << "\\bulletLaTeX " << i << " \""
791 << lyx::to_ascii(user_defined_bullet(i).getText())
797 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
798 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
800 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
801 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
802 for (; a_it != a_end; ++a_it) {
803 if (a_it->second.used())
804 os << "\\author " << a_it->second << "\n";
806 os << "\\author " << Author() << "\n";
811 void BufferParams::validate(LaTeXFeatures & features) const
813 if (!getTextClass().requires().empty()) {
814 vector<string> req = getTextClass().requires();
815 for (vector<string>::const_iterator it = req.begin();
816 it != req.end(); ++it) {
817 features.require(*it);
822 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
823 bool xcolorsoul = LaTeXFeatures::isAvailable("soul") &&
824 LaTeXFeatures::isAvailable("xcolor");
826 switch (features.runparams().flavor) {
827 case OutputParams::LATEX:
829 features.require("ct-dvipost");
830 features.require("dvipost");
831 } else if (xcolorsoul) {
832 features.require("ct-xcolor-soul");
833 features.require("soul");
834 features.require("xcolor");
836 features.require("ct-none");
839 case OutputParams::PDFLATEX:
841 features.require("ct-xcolor-soul");
842 features.require("soul");
843 features.require("xcolor");
844 // improves color handling in PDF output
845 features.require("pdfcolmk");
847 features.require("ct-none");
855 // Floats with 'Here definitely' as default setting.
856 if (float_placement.find('H') != string::npos)
857 features.require("float");
859 // AMS Style is at document level
860 if (use_amsmath == package_on
861 || getTextClass().provides("amsmath"))
862 features.require("amsmath");
863 if (use_esint == package_on)
864 features.require("esint");
866 // Document-level line spacing
867 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
868 features.require("setspace");
870 // the bullet shapes are buffer level not paragraph level
871 // so they are tested here
872 for (int i = 0; i < 4; ++i) {
873 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
875 int const font = user_defined_bullet(i).getFont();
877 int const c = user_defined_bullet(i).getCharacter();
883 features.require("latexsym");
885 } else if (font == 1) {
886 features.require("amssymb");
887 } else if (font >= 2 && font <= 5) {
888 features.require("pifont");
892 if (pdfoptions().use_hyperref)
893 features.require("hyperref");
897 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
898 TexRow & texrow) const
900 os << "\\documentclass";
902 TextClass const & tclass = getTextClass();
904 ostringstream clsoptions; // the document class options.
906 if (tokenPos(tclass.opt_fontsize(),
907 '|', fontsize) >= 0) {
908 // only write if existing in list (and not default)
909 clsoptions << fontsize << "pt,";
912 // custom, A3, B3 and B4 paper sizes need geometry
913 bool nonstandard_papersize = papersize == PAPER_B3
914 || papersize == PAPER_B4
915 || papersize == PAPER_A3
916 || papersize == PAPER_CUSTOM;
921 clsoptions << "a4paper,";
924 clsoptions << "letterpaper,";
927 clsoptions << "a5paper,";
930 clsoptions << "b5paper,";
932 case PAPER_USEXECUTIVE:
933 clsoptions << "executivepaper,";
936 clsoptions << "legalpaper,";
948 if (sides != tclass.sides()) {
951 clsoptions << "oneside,";
954 clsoptions << "twoside,";
960 if (columns != tclass.columns()) {
962 clsoptions << "twocolumn,";
964 clsoptions << "onecolumn,";
968 && orientation == ORIENTATION_LANDSCAPE)
969 clsoptions << "landscape,";
971 // language should be a parameter to \documentclass
972 if (language->babel() == "hebrew"
973 && default_language->babel() != "hebrew")
974 // This seems necessary
975 features.useLanguage(default_language);
977 ostringstream language_options;
978 bool const use_babel = features.useBabel();
980 language_options << features.getLanguages();
981 if (!language->babel().empty()) {
982 if (!language_options.str().empty())
983 language_options << ',';
984 language_options << language->babel();
986 // when Vietnamese is used, babel must directly be loaded with the
987 // language options, not in the class options, see
988 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
989 size_t viet = language_options.str().find("vietnam");
990 // viet = string::npos when not found
991 if (lyxrc.language_global_options && !language_options.str().empty()
992 && viet == string::npos)
993 clsoptions << language_options.str() << ',';
996 // the user-defined options
997 if (!options.empty()) {
998 clsoptions << options << ',';
1001 string strOptions(clsoptions.str());
1002 if (!strOptions.empty()) {
1003 strOptions = rtrim(strOptions, ",");
1005 os << '[' << from_utf8(strOptions) << ']';
1008 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1010 // end of \documentclass defs
1012 // font selection must be done before loading fontenc.sty
1013 string const fonts =
1014 loadFonts(fontsRoman, fontsSans,
1015 fontsTypewriter, fontsSC, fontsOSF,
1016 fontsSansScale, fontsTypewriterScale);
1017 if (!fonts.empty()) {
1018 os << from_ascii(fonts);
1021 if (fontsDefaultFamily != "default")
1022 os << "\\renewcommand{\\familydefault}{\\"
1023 << from_ascii(fontsDefaultFamily) << "}\n";
1025 // set font encoding
1026 // this one is not per buffer
1027 // for arabic_arabi and farsi we also need to load the LAE and LFE encoding
1028 if (lyxrc.fontenc != "default") {
1029 if (language->lang() == "arabic_arabi" || language->lang() == "farsi") {
1030 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1031 << ",LFE,LAE]{fontenc}\n";
1034 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1040 // handle inputenc etc.
1041 writeEncodingPreamble(os, features, texrow);
1043 if (!listings_params.empty()) {
1044 os << "\\usepackage{listings}\n";
1047 // do not test validity because listings_params is supposed to be valid
1048 string par = InsetListingsParams(listings_params).separatedParams(true);
1049 os << from_ascii(par);
1050 // count the number of newlines
1051 for (size_t i = 0; i < par.size(); ++i)
1057 if (use_geometry || nonstandard_papersize) {
1058 os << "\\usepackage{geometry}\n";
1060 os << "\\geometry{verbose";
1061 if (orientation == ORIENTATION_LANDSCAPE)
1063 switch (papersize) {
1065 if (!paperwidth.empty())
1066 os << ",paperwidth="
1067 << from_ascii(paperwidth);
1068 if (!paperheight.empty())
1069 os << ",paperheight="
1070 << from_ascii(paperheight);
1072 case PAPER_USLETTER:
1073 os << ",letterpaper";
1076 os << ",legalpaper";
1078 case PAPER_USEXECUTIVE:
1079 os << ",executivepaper";
1100 // default papersize ie PAPER_DEFAULT
1101 switch (lyxrc.default_papersize) {
1102 case PAPER_DEFAULT: // keep compiler happy
1103 case PAPER_USLETTER:
1104 os << ",letterpaper";
1107 os << ",legalpaper";
1109 case PAPER_USEXECUTIVE:
1110 os << ",executivepaper";
1130 if (!topmargin.empty())
1131 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1132 if (!bottommargin.empty())
1133 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1134 if (!leftmargin.empty())
1135 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1136 if (!rightmargin.empty())
1137 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1138 if (!headheight.empty())
1139 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1140 if (!headsep.empty())
1141 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1142 if (!footskip.empty())
1143 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1148 if (tokenPos(tclass.opt_pagestyle(),
1149 '|', pagestyle) >= 0) {
1150 if (pagestyle == "fancy") {
1151 os << "\\usepackage{fancyhdr}\n";
1154 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1158 // Only if class has a ToC hierarchy
1159 if (tclass.hasTocLevels()) {
1160 if (secnumdepth != tclass.secnumdepth()) {
1161 os << "\\setcounter{secnumdepth}{"
1166 if (tocdepth != tclass.tocdepth()) {
1167 os << "\\setcounter{tocdepth}{"
1174 if (paragraph_separation) {
1175 switch (getDefSkip().kind()) {
1176 case VSpace::SMALLSKIP:
1177 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1179 case VSpace::MEDSKIP:
1180 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1182 case VSpace::BIGSKIP:
1183 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1185 case VSpace::LENGTH:
1186 os << "\\setlength{\\parskip}{"
1187 << from_utf8(getDefSkip().length().asLatexString())
1190 default: // should never happen // Then delete it.
1191 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1196 os << "\\setlength{\\parindent}{0pt}\n";
1200 // If we use jurabib, we have to call babel here.
1201 if (use_babel && features.isRequired("jurabib")) {
1202 os << from_ascii(babelCall(language_options.str()))
1204 << from_ascii(features.getBabelOptions());
1208 // Now insert the LyX specific LaTeX commands...
1210 // The optional packages;
1211 docstring lyxpreamble(from_ascii(features.getPackages()));
1214 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1216 // We try to load babel late, in case it interferes
1217 // with other packages. But some packages also need babel to be loaded
1218 // before, e.g. jurabib has to be called after babel.
1219 // So load babel after the optional packages but before the user-defined
1220 // preamble. This allows the users to redefine babel commands, e.g. to
1221 // translate the word "Index" to the German "Stichwortverzeichnis".
1222 // For more infos why this place was chosen, see
1223 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg128425.html
1224 // If you encounter problems, you can shift babel to its old place behind
1225 // the user-defined preamble. But in this case you must change the Vietnamese
1226 // support from currently "\usepackage[vietnamese]{babel}" to:
1227 // \usepackage{vietnamese}
1228 // \usepackage{babel}
1229 // because vietnamese must be loaded before hyperref
1230 if (use_babel && !features.isRequired("jurabib")) {
1232 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1233 lyxpreamble += from_utf8(features.getBabelOptions());
1236 // When the language "japanese-plain" is used, the package "japanese" must
1237 // be loaded behind babel (it provides babel support for Japanese) but before
1239 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1240 if (language->lang() == "japanese-plain" &&
1241 !getTextClass().provides("japanese")) {
1242 //load babel in case it was not loaded due to an empty language list
1243 if (language_options.str().empty())
1244 lyxpreamble += "\\usepackage{babel}\n";
1245 lyxpreamble += "\\usepackage{japanese}\n";
1249 // * Hyperref manual: "Make sure it comes last of your loaded
1250 // packages, to give it a fighting chance of not being over-written,
1251 // since its job is to redefine many LATEX commands."
1252 // * Email from Heiko Oberdiek: "It is usually better to load babel
1253 // before hyperref. Then hyperref has a chance to detect babel.
1254 // * Has to be loaded before the "LyX specific LaTeX commands" to
1255 // avoid errors with algorithm floats.
1256 // use hyperref explicitely when it is required
1257 /** FIXME: If the textclass provides hyperref, the GUI is
1258 non-functional. To fix this, we would need requires("hyperref")
1259 below, pass getTextClass().provides("hyperref") to
1260 pdfoptions().writeLaTeX(oss) and load the options via
1261 \hypersetup instead of tha package's optional argument.
1263 if (features.mustProvide("hyperref")) {
1264 odocstringstream oss;
1265 pdfoptions().writeLaTeX(oss);
1266 lyxpreamble += oss.str();
1269 // this might be useful...
1270 lyxpreamble += "\n\\makeatletter\n";
1272 // Some macros LyX will need
1273 docstring tmppreamble(from_ascii(features.getMacros()));
1275 if (!tmppreamble.empty()) {
1276 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1277 "LyX specific LaTeX commands.\n"
1278 + tmppreamble + '\n';
1281 // the text class specific preamble
1282 tmppreamble = features.getTClassPreamble();
1283 if (!tmppreamble.empty()) {
1284 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1285 "Textclass specific LaTeX commands.\n"
1286 + tmppreamble + '\n';
1289 /* the user-defined preamble */
1290 if (!preamble.empty()) {
1292 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1293 "User specified LaTeX commands.\n"
1294 + from_utf8(preamble) + '\n';
1297 // Itemize bullet settings need to be last in case the user
1298 // defines their own bullets that use a package included
1299 // in the user-defined preamble -- ARRae
1300 // Actually it has to be done much later than that
1301 // since some packages like frenchb make modifications
1302 // at \begin{document} time -- JMarc
1303 docstring bullets_def;
1304 for (int i = 0; i < 4; ++i) {
1305 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1306 if (bullets_def.empty())
1307 bullets_def += "\\AtBeginDocument{\n";
1308 bullets_def += " \\def\\labelitemi";
1310 // `i' is one less than the item to modify
1317 bullets_def += "ii";
1323 bullets_def += '{' +
1324 user_defined_bullet(i).getText()
1329 if (!bullets_def.empty())
1330 lyxpreamble += bullets_def + "}\n\n";
1332 lyxpreamble += "\\makeatother\n\n";
1335 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1336 for (int j = 0; j != nlines; ++j) {
1345 void BufferParams::useClassDefaults()
1347 TextClass const & tclass = textclasslist[baseClass_];
1349 sides = tclass.sides();
1350 columns = tclass.columns();
1351 pagestyle = tclass.pagestyle();
1352 options = tclass.options();
1353 // Only if class has a ToC hierarchy
1354 if (tclass.hasTocLevels()) {
1355 secnumdepth = tclass.secnumdepth();
1356 tocdepth = tclass.tocdepth();
1361 bool BufferParams::hasClassDefaults() const
1363 TextClass const & tclass = textclasslist[baseClass_];
1365 return (sides == tclass.sides()
1366 && columns == tclass.columns()
1367 && pagestyle == tclass.pagestyle()
1368 && options == tclass.options()
1369 && secnumdepth == tclass.secnumdepth()
1370 && tocdepth == tclass.tocdepth());
1374 TextClass const & BufferParams::getTextClass() const
1380 TextClassPtr BufferParams::getTextClassPtr() const {
1385 void BufferParams::setTextClass(TextClassPtr tc) {
1390 bool BufferParams::setBaseClass(textclass_type tc)
1392 if (textclasslist[tc].load()) {
1398 bformat(_("The document class %1$s could not be loaded."),
1399 from_utf8(textclasslist[tc].name()));
1400 frontend::Alert::error(_("Could not load class"), s);
1405 textclass_type BufferParams::getBaseClass() const
1411 void BufferParams::makeTextClass()
1413 textClass_.reset(new TextClass(textclasslist[getBaseClass()]));
1415 //FIXME It might be worth loading the children's modules here,
1416 //just as we load their bibliographies and such, instead of just
1417 //doing a check in InsetInclude.
1418 LayoutModuleList::const_iterator it = layoutModules_.begin();
1419 for (; it != layoutModules_.end(); it++) {
1420 string const modName = *it;
1421 LyXModule * lm = moduleList[modName];
1423 docstring const msg =
1424 bformat(_("The module %1$s has been requested by\n"
1425 "this document but has not been found in the list of\n"
1426 "available modules. If you recently installed it, you\n"
1427 "probably need to reconfigure LyX.\n"), from_utf8(modName));
1428 frontend::Alert::warning(_("Module not available"),
1429 msg + _("Some layouts may not be available."));
1430 lyxerr << "BufferParams::makeTextClass(): Module " <<
1431 modName << " requested but not found in module list." <<
1435 if (!lm->isAvailable()) {
1436 docstring const msg =
1437 bformat(_("The module %1$s requires a package that is\n"
1438 "not available in your LaTeX installation. LaTeX output\n"
1439 "may not be possible.\n"), from_utf8(modName));
1440 frontend::Alert::warning(_("Package not available"), msg);
1442 FileName layout_file = libFileSearch("layouts", lm->getFilename());
1443 textClass_->read(layout_file, TextClass::MODULE);
1448 vector<string> const & BufferParams::getModules() const {
1449 return layoutModules_;
1454 bool BufferParams::addLayoutModule(string const & modName) {
1455 LayoutModuleList::const_iterator it = layoutModules_.begin();
1456 LayoutModuleList::const_iterator end = layoutModules_.end();
1457 for (; it != end; it++) {
1461 if (it != layoutModules_.end())
1463 layoutModules_.push_back(modName);
1468 void BufferParams::clearLayoutModules() {
1469 layoutModules_.clear();
1473 Font const BufferParams::getFont() const
1475 FontInfo f = getTextClass().defaultfont();
1476 if (fontsDefaultFamily == "rmdefault")
1477 f.setFamily(ROMAN_FAMILY);
1478 else if (fontsDefaultFamily == "sfdefault")
1479 f.setFamily(SANS_FAMILY);
1480 else if (fontsDefaultFamily == "ttdefault")
1481 f.setFamily(TYPEWRITER_FAMILY);
1482 return Font(f, language);
1486 void BufferParams::readPreamble(Lexer & lex)
1488 if (lex.getString() != "\\begin_preamble")
1489 lyxerr << "Error (BufferParams::readPreamble):"
1490 "consistency check failed." << endl;
1492 preamble = lex.getLongString("\\end_preamble");
1496 void BufferParams::readLanguage(Lexer & lex)
1498 if (!lex.next()) return;
1500 string const tmptok = lex.getString();
1502 // check if tmptok is part of tex_babel in tex-defs.h
1503 language = languages.getLanguage(tmptok);
1505 // Language tmptok was not found
1506 language = default_language;
1507 lyxerr << "Warning: Setting language `"
1508 << tmptok << "' to `" << language->lang()
1514 void BufferParams::readGraphicsDriver(Lexer & lex)
1516 if (!lex.next()) return;
1518 string const tmptok = lex.getString();
1519 // check if tmptok is part of tex_graphics in tex_defs.h
1522 string const test = tex_graphics[n++];
1524 if (test == tmptok) {
1525 graphicsDriver = tmptok;
1527 } else if (test == "") {
1529 "Warning: graphics driver `$$Token' not recognized!\n"
1530 " Setting graphics driver to `default'.\n");
1531 graphicsDriver = "default";
1538 void BufferParams::readBullets(Lexer & lex)
1540 if (!lex.next()) return;
1542 int const index = lex.getInteger();
1544 int temp_int = lex.getInteger();
1545 user_defined_bullet(index).setFont(temp_int);
1546 temp_bullet(index).setFont(temp_int);
1548 user_defined_bullet(index).setCharacter(temp_int);
1549 temp_bullet(index).setCharacter(temp_int);
1551 user_defined_bullet(index).setSize(temp_int);
1552 temp_bullet(index).setSize(temp_int);
1556 void BufferParams::readBulletsLaTeX(Lexer & lex)
1558 // The bullet class should be able to read this.
1559 if (!lex.next()) return;
1560 int const index = lex.getInteger();
1562 docstring const temp_str = lex.getDocString();
1564 user_defined_bullet(index).setText(temp_str);
1565 temp_bullet(index).setText(temp_str);
1569 void BufferParams::readModules(Lexer & lex)
1571 if (!lex.eatLine()) {
1572 lyxerr << "Error (BufferParams::readModules):"
1573 "Unexpected end of input." << endl;
1577 string mod = lex.getString();
1578 if (mod == "\\end_modules")
1580 addLayoutModule(mod);
1586 string const BufferParams::paperSizeName() const
1588 char real_papersize = papersize;
1589 if (real_papersize == PAPER_DEFAULT)
1590 real_papersize = lyxrc.default_papersize;
1592 switch (real_papersize) {
1601 case PAPER_USEXECUTIVE:
1605 case PAPER_USLETTER:
1612 string const BufferParams::dvips_options() const
1617 && papersize == PAPER_CUSTOM
1618 && !lyxrc.print_paper_dimension_flag.empty()
1619 && !paperwidth.empty()
1620 && !paperheight.empty()) {
1621 // using a custom papersize
1622 result = lyxrc.print_paper_dimension_flag;
1623 result += ' ' + paperwidth;
1624 result += ',' + paperheight;
1626 string const paper_option = paperSizeName();
1627 if (paper_option != "letter" ||
1628 orientation != ORIENTATION_LANDSCAPE) {
1629 // dvips won't accept -t letter -t landscape.
1630 // In all other cases, include the paper size
1632 result = lyxrc.print_paper_flag;
1633 result += ' ' + paper_option;
1636 if (orientation == ORIENTATION_LANDSCAPE &&
1637 papersize != PAPER_CUSTOM)
1638 result += ' ' + lyxrc.print_landscape_flag;
1643 string const BufferParams::babelCall(string const & lang_opts) const
1645 string lang_pack = lyxrc.language_package;
1646 if (lang_pack != "\\usepackage{babel}")
1648 // suppress the babel call when there is no babel language defined
1649 // for the document language in the lib/languages file and if no
1650 // other languages are used (lang_opts is then empty)
1651 if (lang_opts.empty())
1653 // when Vietnamese is used, babel must directly be loaded with the
1654 // language options, see
1655 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1656 size_t viet = lang_opts.find("vietnam");
1657 // viet = string::npos when not found
1658 if (!lyxrc.language_global_options || viet != string::npos)
1659 return "\\usepackage[" + lang_opts + "]{babel}";
1664 void BufferParams::writeEncodingPreamble(odocstream & os,
1665 LaTeXFeatures & features, TexRow & texrow) const
1667 if (inputenc == "auto") {
1668 string const doc_encoding =
1669 language->encoding()->latexName();
1670 Encoding::Package const package =
1671 language->encoding()->package();
1673 // Create a list with all the input encodings used
1675 set<string> encodings =
1676 features.getEncodingSet(doc_encoding);
1678 // When the encodings EUC-JP-plain, JIS-plain, or SJIS-plainare used, the
1679 // package inputenc must be omitted. Therefore set the encoding to empty.
1680 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1681 if (doc_encoding == "EUC-JP-plain" || doc_encoding == "JIS-plain" ||
1682 doc_encoding == "SJIS-plain")
1685 if (!encodings.empty() || package == Encoding::inputenc) {
1686 os << "\\usepackage[";
1687 set<string>::const_iterator it = encodings.begin();
1688 set<string>::const_iterator const end = encodings.end();
1690 os << from_ascii(*it);
1693 for (; it != end; ++it)
1694 os << ',' << from_ascii(*it);
1695 if (package == Encoding::inputenc) {
1696 if (!encodings.empty())
1698 os << from_ascii(doc_encoding);
1700 os << "]{inputenc}\n";
1703 if (package == Encoding::CJK || features.mustProvide("CJK")) {
1704 os << "\\usepackage{CJK}\n";
1707 } else if (inputenc != "default") {
1708 switch (encoding().package()) {
1709 case Encoding::none:
1711 case Encoding::inputenc:
1712 os << "\\usepackage[" << from_ascii(inputenc)
1717 os << "\\usepackage{CJK}\n";
1723 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1724 // armscii8 is used for Armenian.
1725 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1726 os << "\\usepackage{armtex}\n";
1732 string const BufferParams::loadFonts(string const & rm,
1733 string const & sf, string const & tt,
1734 bool const & sc, bool const & osf,
1735 int const & sfscale, int const & ttscale) const
1737 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1738 several packages have been replaced by others, that might not
1739 be installed on every system. We have to take care for that
1740 (see psnfss.pdf). We try to support all psnfss fonts as well
1741 as the fonts that have become de facto standard in the LaTeX
1742 world (e.g. Latin Modern). We do not support obsolete fonts
1743 (like PSLatex). In general, it should be possible to mix any
1744 rm font with any sf or tt font, respectively. (JSpitzm)
1746 -- separate math fonts.
1749 if (rm == "default" && sf == "default" && tt == "default")
1756 // Computer Modern (must be explicitely selectable -- there might be classes
1757 // that define a different default font!
1759 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1760 // osf for Computer Modern needs eco.sty
1762 os << "\\usepackage{eco}\n";
1764 // Latin Modern Roman
1765 else if (rm == "lmodern")
1766 os << "\\usepackage{lmodern}\n";
1768 else if (rm == "ae") {
1769 // not needed when using OT1 font encoding.
1770 if (lyxrc.fontenc != "default")
1771 os << "\\usepackage{ae,aecompl}\n";
1774 else if (rm == "times") {
1775 // try to load the best available package
1776 if (LaTeXFeatures::isAvailable("mathptmx"))
1777 os << "\\usepackage{mathptmx}\n";
1778 else if (LaTeXFeatures::isAvailable("mathptm"))
1779 os << "\\usepackage{mathptm}\n";
1781 os << "\\usepackage{times}\n";
1784 else if (rm == "palatino") {
1785 // try to load the best available package
1786 if (LaTeXFeatures::isAvailable("mathpazo")) {
1787 os << "\\usepackage";
1793 // "osf" includes "sc"!
1797 os << "{mathpazo}\n";
1799 else if (LaTeXFeatures::isAvailable("mathpple"))
1800 os << "\\usepackage{mathpple}\n";
1802 os << "\\usepackage{palatino}\n";
1805 else if (rm == "utopia") {
1806 // fourier supersedes utopia.sty, but does
1807 // not work with OT1 encoding.
1808 if (LaTeXFeatures::isAvailable("fourier")
1809 && lyxrc.fontenc != "default") {
1810 os << "\\usepackage";
1821 os << "{fourier}\n";
1824 os << "\\usepackage{utopia}\n";
1826 // Bera (complete fontset)
1827 else if (rm == "bera" && sf == "default" && tt == "default")
1828 os << "\\usepackage{bera}\n";
1830 else if (rm != "default")
1831 os << "\\usepackage" << "{" << rm << "}\n";
1834 // Helvetica, Bera Sans
1835 if (sf == "helvet" || sf == "berasans") {
1837 os << "\\usepackage[scaled=" << float(sfscale) / 100
1838 << "]{" << sf << "}\n";
1840 os << "\\usepackage{" << sf << "}\n";
1843 else if (sf == "avant")
1844 os << "\\usepackage{" << sf << "}\n";
1845 // Computer Modern, Latin Modern, CM Bright
1846 else if (sf != "default")
1847 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1849 // monospaced/typewriter
1850 // Courier, LuxiMono
1851 if (tt == "luximono" || tt == "beramono") {
1853 os << "\\usepackage[scaled=" << float(ttscale) / 100
1854 << "]{" << tt << "}\n";
1856 os << "\\usepackage{" << tt << "}\n";
1859 else if (tt == "courier" )
1860 os << "\\usepackage{" << tt << "}\n";
1861 // Computer Modern, Latin Modern, CM Bright
1862 else if (tt != "default")
1863 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1869 Encoding const & BufferParams::encoding() const
1871 if (inputenc == "auto" || inputenc == "default")
1872 return *(language->encoding());
1873 Encoding const * const enc =
1874 encodings.getFromLaTeXName(inputenc);
1877 lyxerr << "Unknown inputenc value `" << inputenc
1878 << "'. Using `auto' instead." << endl;
1879 return *(language->encoding());
1883 biblio::CiteEngine BufferParams::getEngine() const
1885 // FIXME the class should provide the numerical/
1886 // authoryear choice
1887 if (getTextClass().provides("natbib")
1888 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1889 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1890 return cite_engine_;
1894 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1896 cite_engine_ = cite_engine;