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 "LayoutFile.h"
22 #include "BranchList.h"
23 #include "buffer_funcs.h"
29 #include "LaTeXFeatures.h"
30 #include "ModuleList.h"
34 #include "OutputParams.h"
38 #include "PDFOptions.h"
40 #include "frontends/alert.h"
42 #include "insets/InsetListingsParams.h"
44 #include "support/convert.h"
45 #include "support/debug.h"
46 #include "support/docstream.h"
47 #include "support/FileName.h"
48 #include "support/filetools.h"
49 #include "support/gettext.h"
50 #include "support/Messages.h"
51 #include "support/Translator.h"
52 #include "support/lstrings.h"
58 using namespace lyx::support;
61 static char const * const string_paragraph_separation[] = {
66 static char const * const string_quotes_language[] = {
67 "english", "swedish", "german", "polish", "french", "danish", ""
71 static char const * const string_papersize[] = {
72 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
73 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
77 static char const * const string_orientation[] = {
78 "portrait", "landscape", ""
82 static char const * const string_footnotekinds[] = {
83 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
87 static char const * const tex_graphics[] = {
88 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
89 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
90 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
91 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
101 // Paragraph separation
102 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
105 ParSepTranslator const init_parseptranslator()
107 ParSepTranslator translator
108 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
109 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
114 ParSepTranslator const & parseptranslator()
116 static ParSepTranslator translator = init_parseptranslator();
122 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
125 QuotesLangTranslator const init_quoteslangtranslator()
127 QuotesLangTranslator translator
128 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
129 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
130 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
131 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
132 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
133 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
138 QuotesLangTranslator const & quoteslangtranslator()
140 static QuotesLangTranslator translator = init_quoteslangtranslator();
146 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
149 static PaperSizeTranslator initPaperSizeTranslator()
151 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
152 translator.addPair(string_papersize[1], PAPER_CUSTOM);
153 translator.addPair(string_papersize[2], PAPER_USLETTER);
154 translator.addPair(string_papersize[3], PAPER_USLEGAL);
155 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
156 translator.addPair(string_papersize[5], PAPER_A3);
157 translator.addPair(string_papersize[6], PAPER_A4);
158 translator.addPair(string_papersize[7], PAPER_A5);
159 translator.addPair(string_papersize[8], PAPER_B3);
160 translator.addPair(string_papersize[9], PAPER_B4);
161 translator.addPair(string_papersize[10], PAPER_B5);
166 PaperSizeTranslator const & papersizetranslator()
168 static PaperSizeTranslator translator = initPaperSizeTranslator();
174 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
177 PaperOrientationTranslator const init_paperorientationtranslator()
179 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
180 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
185 PaperOrientationTranslator const & paperorientationtranslator()
187 static PaperOrientationTranslator translator = init_paperorientationtranslator();
193 typedef Translator<int, PageSides> SidesTranslator;
196 SidesTranslator const init_sidestranslator()
198 SidesTranslator translator(1, OneSide);
199 translator.addPair(2, TwoSides);
204 SidesTranslator const & sidestranslator()
206 static SidesTranslator translator = init_sidestranslator();
212 typedef Translator<int, BufferParams::Package> PackageTranslator;
215 PackageTranslator const init_packagetranslator()
217 PackageTranslator translator(0, BufferParams::package_off);
218 translator.addPair(1, BufferParams::package_auto);
219 translator.addPair(2, BufferParams::package_on);
224 PackageTranslator const & packagetranslator()
226 static PackageTranslator translator = init_packagetranslator();
232 typedef Translator<string, CiteEngine> CiteEngineTranslator;
235 CiteEngineTranslator const init_citeenginetranslator()
237 CiteEngineTranslator translator("basic", ENGINE_BASIC);
238 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
239 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
240 translator.addPair("jurabib", ENGINE_JURABIB);
245 CiteEngineTranslator const & citeenginetranslator()
247 static CiteEngineTranslator translator = init_citeenginetranslator();
253 typedef Translator<string, Spacing::Space> SpaceTranslator;
256 SpaceTranslator const init_spacetranslator()
258 SpaceTranslator translator("default", Spacing::Default);
259 translator.addPair("single", Spacing::Single);
260 translator.addPair("onehalf", Spacing::Onehalf);
261 translator.addPair("double", Spacing::Double);
262 translator.addPair("other", Spacing::Other);
267 SpaceTranslator const & spacetranslator()
269 static SpaceTranslator translator = init_spacetranslator();
277 class BufferParams::Impl
282 AuthorList authorlist;
283 BranchList branchlist;
284 Bullet temp_bullets[4];
285 Bullet user_defined_bullets[4];
287 /** This is the amount of space used for paragraph_separation "skip",
288 * and for detached paragraphs in "indented" documents.
291 PDFOptions pdfoptions;
292 LayoutFileIndex baseClass_;
296 BufferParams::Impl::Impl()
297 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
299 // set initial author
301 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
306 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
310 return new BufferParams::Impl(*ptr);
314 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
320 BufferParams::BufferParams()
323 setBaseClass(defaultBaseclass());
325 paragraph_separation = ParagraphIndentSeparation;
326 quotes_language = InsetQuotes::EnglishQuotes;
327 fontsize = "default";
330 papersize = PAPER_DEFAULT;
331 orientation = ORIENTATION_PORTRAIT;
332 use_geometry = false;
333 use_amsmath = package_auto;
334 use_esint = package_auto;
335 cite_engine_ = ENGINE_BASIC;
336 use_bibtopic = false;
337 trackChanges = false;
338 outputChanges = false;
339 use_default_options = true;
342 language = default_language;
343 fontsRoman = "default";
344 fontsSans = "default";
345 fontsTypewriter = "default";
346 fontsDefaultFamily = "default";
349 fontsSansScale = 100;
350 fontsTypewriterScale = 100;
352 graphicsDriver = "default";
355 listings_params = string();
356 pagestyle = "default";
358 for (int iter = 0; iter < 4; ++iter) {
359 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
360 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
365 docstring BufferParams::B_(string const & l10n) const
367 LASSERT(language, /**/);
368 return getMessages(language->code()).get(l10n);
372 AuthorList & BufferParams::authors()
374 return pimpl_->authorlist;
378 AuthorList const & BufferParams::authors() const
380 return pimpl_->authorlist;
384 BranchList & BufferParams::branchlist()
386 return pimpl_->branchlist;
390 BranchList const & BufferParams::branchlist() const
392 return pimpl_->branchlist;
396 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
398 LASSERT(index < 4, /**/);
399 return pimpl_->temp_bullets[index];
403 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
405 LASSERT(index < 4, /**/);
406 return pimpl_->temp_bullets[index];
410 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
412 LASSERT(index < 4, /**/);
413 return pimpl_->user_defined_bullets[index];
417 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
419 LASSERT(index < 4, /**/);
420 return pimpl_->user_defined_bullets[index];
424 Spacing & BufferParams::spacing()
426 return pimpl_->spacing;
430 Spacing const & BufferParams::spacing() const
432 return pimpl_->spacing;
436 PDFOptions & BufferParams::pdfoptions()
438 return pimpl_->pdfoptions;
442 PDFOptions const & BufferParams::pdfoptions() const
444 return pimpl_->pdfoptions;
448 VSpace const & BufferParams::getDefSkip() const
450 return pimpl_->defskip;
454 void BufferParams::setDefSkip(VSpace const & vs)
456 pimpl_->defskip = vs;
460 string BufferParams::readToken(Lexer & lex, string const & token,
461 FileName const & filepath)
463 if (token == "\\textclass") {
465 string const classname = lex.getString();
466 // if there exists a local layout file, ignore the system one
467 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
469 LayoutFileList & bcl = LayoutFileList::get();
470 if (tcp.empty() && !filepath.empty())
471 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
475 setBaseClass(classname);
476 // We assume that a tex class exists for local or unknown layouts so this warning
477 // will only be given for system layouts.
478 if (!baseClass()->isTeXClassAvailable()) {
479 docstring const msg =
480 bformat(_("The layout file requested by this document,\n"
482 "is not usable. This is probably because a LaTeX\n"
483 "class or style file required by it is not\n"
484 "available. See the Customization documentation\n"
485 "for more information.\n"), from_utf8(classname));
486 frontend::Alert::warning(_("Document class not available"),
487 msg + _("LyX will not be able to produce output."));
489 } else if (token == "\\begin_preamble") {
491 } else if (token == "\\begin_local_layout") {
492 readLocalLayout(lex);
493 } else if (token == "\\begin_modules") {
495 } else if (token == "\\begin_removed_modules") {
496 readRemovedModules(lex);
497 } else if (token == "\\options") {
499 options = lex.getString();
500 } else if (token == "\\use_default_options") {
501 lex >> use_default_options;
502 } else if (token == "\\master") {
504 master = lex.getString();
505 } else if (token == "\\language") {
507 } else if (token == "\\inputencoding") {
509 } else if (token == "\\graphics") {
510 readGraphicsDriver(lex);
511 } else if (token == "\\font_roman") {
513 } else if (token == "\\font_sans") {
515 } else if (token == "\\font_typewriter") {
516 lex >> fontsTypewriter;
517 } else if (token == "\\font_default_family") {
518 lex >> fontsDefaultFamily;
519 } else if (token == "\\font_sc") {
521 } else if (token == "\\font_osf") {
523 } else if (token == "\\font_sf_scale") {
524 lex >> fontsSansScale;
525 } else if (token == "\\font_tt_scale") {
526 lex >> fontsTypewriterScale;
527 } else if (token == "\\font_cjk") {
529 } else if (token == "\\paragraph_separation") {
532 paragraph_separation = parseptranslator().find(parsep);
533 } else if (token == "\\defskip") {
535 string defskip = lex.getString();
536 if (defskip == "defskip")
539 pimpl_->defskip = VSpace(defskip);
540 } else if (token == "\\quotes_language") {
543 quotes_language = quoteslangtranslator().find(quotes_lang);
544 } else if (token == "\\papersize") {
547 papersize = papersizetranslator().find(ppsize);
548 } else if (token == "\\use_geometry") {
550 } else if (token == "\\use_amsmath") {
553 use_amsmath = packagetranslator().find(use_ams);
554 } else if (token == "\\use_esint") {
557 use_esint = packagetranslator().find(useesint);
558 } else if (token == "\\cite_engine") {
561 cite_engine_ = citeenginetranslator().find(engine);
562 } else if (token == "\\use_bibtopic") {
564 } else if (token == "\\tracking_changes") {
566 } else if (token == "\\output_changes") {
567 lex >> outputChanges;
568 } else if (token == "\\branch") {
570 docstring branch = lex.getDocString();
571 branchlist().add(branch);
574 string const tok = lex.getString();
575 if (tok == "\\end_branch")
577 Branch * branch_ptr = branchlist().find(branch);
578 if (tok == "\\selected") {
581 branch_ptr->setSelected(lex.getInteger());
583 // not yet operational
584 if (tok == "\\color") {
586 string color = lex.getString();
588 branch_ptr->setColor(color);
589 // Update also the Color table:
591 color = lcolor.getX11Name(Color_background);
593 lcolor.setColor(to_utf8(branch), color);
597 } else if (token == "\\author") {
599 istringstream ss(lex.getString());
602 author_map.push_back(pimpl_->authorlist.record(a));
603 } else if (token == "\\paperorientation") {
606 orientation = paperorientationtranslator().find(orient);
607 } else if (token == "\\paperwidth") {
609 } else if (token == "\\paperheight") {
611 } else if (token == "\\leftmargin") {
613 } else if (token == "\\topmargin") {
615 } else if (token == "\\rightmargin") {
617 } else if (token == "\\bottommargin") {
619 } else if (token == "\\headheight") {
621 } else if (token == "\\headsep") {
623 } else if (token == "\\footskip") {
625 } else if (token == "\\columnsep") {
627 } else if (token == "\\paperfontsize") {
629 } else if (token == "\\papercolumns") {
631 } else if (token == "\\listings_params") {
634 listings_params = InsetListingsParams(par).params();
635 } else if (token == "\\papersides") {
638 sides = sidestranslator().find(psides);
639 } else if (token == "\\paperpagestyle") {
641 } else if (token == "\\bullet") {
643 } else if (token == "\\bulletLaTeX") {
644 readBulletsLaTeX(lex);
645 } else if (token == "\\secnumdepth") {
647 } else if (token == "\\tocdepth") {
649 } else if (token == "\\spacing") {
653 if (nspacing == "other") {
656 spacing().set(spacetranslator().find(nspacing), tmp_val);
657 } else if (token == "\\float_placement") {
658 lex >> float_placement;
660 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
661 string toktmp = pdfoptions().readToken(lex, token);
662 if (!toktmp.empty()) {
663 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
668 lyxerr << "BufferParams::readToken(): Unknown token: " <<
677 void BufferParams::writeFile(ostream & os) const
679 // The top of the file is written by the buffer.
680 // Prints out the buffer info into the .lyx file given by file
683 os << "\\textclass " << baseClass()->name() << '\n';
686 if (!preamble.empty()) {
687 // remove '\n' from the end of preamble
688 string const tmppreamble = rtrim(preamble, "\n");
689 os << "\\begin_preamble\n"
691 << "\n\\end_preamble\n";
695 if (!options.empty()) {
696 os << "\\options " << options << '\n';
699 // use the class options defined in the layout?
700 os << "\\use_default_options "
701 << convert<string>(use_default_options) << "\n";
703 // the master document
704 if (!master.empty()) {
705 os << "\\master " << master << '\n';
709 if (!removedModules_.empty()) {
710 os << "\\begin_removed_modules" << '\n';
711 list<string>::const_iterator it = removedModules_.begin();
712 list<string>::const_iterator en = removedModules_.end();
713 for (; it != en; it++)
715 os << "\\end_removed_modules" << '\n';
719 if (!layoutModules_.empty()) {
720 os << "\\begin_modules" << '\n';
721 LayoutModuleList::const_iterator it = layoutModules_.begin();
722 LayoutModuleList::const_iterator en = layoutModules_.end();
723 for (; it != en; it++)
725 os << "\\end_modules" << '\n';
728 // local layout information
729 if (!local_layout.empty()) {
730 // remove '\n' from the end
731 string const tmplocal = rtrim(local_layout, "\n");
732 os << "\\begin_local_layout\n"
734 << "\n\\end_local_layout\n";
737 // then the text parameters
738 if (language != ignore_language)
739 os << "\\language " << language->lang() << '\n';
740 os << "\\inputencoding " << inputenc
741 << "\n\\font_roman " << fontsRoman
742 << "\n\\font_sans " << fontsSans
743 << "\n\\font_typewriter " << fontsTypewriter
744 << "\n\\font_default_family " << fontsDefaultFamily
745 << "\n\\font_sc " << convert<string>(fontsSC)
746 << "\n\\font_osf " << convert<string>(fontsOSF)
747 << "\n\\font_sf_scale " << fontsSansScale
748 << "\n\\font_tt_scale " << fontsTypewriterScale
750 if (!fontsCJK.empty()) {
751 os << "\\font_cjk " << fontsCJK << '\n';
753 os << "\n\\graphics " << graphicsDriver << '\n';
755 if (!float_placement.empty()) {
756 os << "\\float_placement " << float_placement << '\n';
758 os << "\\paperfontsize " << fontsize << '\n';
760 spacing().writeFile(os);
761 pdfoptions().writeFile(os);
763 os << "\\papersize " << string_papersize[papersize]
764 << "\n\\use_geometry " << convert<string>(use_geometry)
765 << "\n\\use_amsmath " << use_amsmath
766 << "\n\\use_esint " << use_esint
767 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
768 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
769 << "\n\\paperorientation " << string_orientation[orientation]
772 BranchList::const_iterator it = branchlist().begin();
773 BranchList::const_iterator end = branchlist().end();
774 for (; it != end; ++it) {
775 os << "\\branch " << to_utf8(it->branch())
776 << "\n\\selected " << it->isSelected()
777 << "\n\\color " << lyx::X11hexname(it->color())
782 if (!paperwidth.empty())
783 os << "\\paperwidth "
784 << VSpace(paperwidth).asLyXCommand() << '\n';
785 if (!paperheight.empty())
786 os << "\\paperheight "
787 << VSpace(paperheight).asLyXCommand() << '\n';
788 if (!leftmargin.empty())
789 os << "\\leftmargin "
790 << VSpace(leftmargin).asLyXCommand() << '\n';
791 if (!topmargin.empty())
793 << VSpace(topmargin).asLyXCommand() << '\n';
794 if (!rightmargin.empty())
795 os << "\\rightmargin "
796 << VSpace(rightmargin).asLyXCommand() << '\n';
797 if (!bottommargin.empty())
798 os << "\\bottommargin "
799 << VSpace(bottommargin).asLyXCommand() << '\n';
800 if (!headheight.empty())
801 os << "\\headheight "
802 << VSpace(headheight).asLyXCommand() << '\n';
803 if (!headsep.empty())
805 << VSpace(headsep).asLyXCommand() << '\n';
806 if (!footskip.empty())
808 << VSpace(footskip).asLyXCommand() << '\n';
809 if (!columnsep.empty())
811 << VSpace(columnsep).asLyXCommand() << '\n';
812 os << "\\secnumdepth " << secnumdepth
813 << "\n\\tocdepth " << tocdepth
814 << "\n\\paragraph_separation "
815 << string_paragraph_separation[paragraph_separation]
816 << "\n\\defskip " << getDefSkip().asLyXCommand()
817 << "\n\\quotes_language "
818 << string_quotes_language[quotes_language]
819 << "\n\\papercolumns " << columns
820 << "\n\\papersides " << sides
821 << "\n\\paperpagestyle " << pagestyle << '\n';
822 if (!listings_params.empty())
823 os << "\\listings_params \"" <<
824 InsetListingsParams(listings_params).encodedString() << "\"\n";
825 for (int i = 0; i < 4; ++i) {
826 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
827 if (user_defined_bullet(i).getFont() != -1) {
828 os << "\\bullet " << i << " "
829 << user_defined_bullet(i).getFont() << " "
830 << user_defined_bullet(i).getCharacter() << " "
831 << user_defined_bullet(i).getSize() << "\n";
835 os << "\\bulletLaTeX " << i << " \""
836 << lyx::to_ascii(user_defined_bullet(i).getText())
842 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
843 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
845 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
846 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
847 for (; a_it != a_end; ++a_it) {
848 if (a_it->second.used())
849 os << "\\author " << a_it->second << "\n";
851 os << "\\author " << Author() << "\n";
856 void BufferParams::validate(LaTeXFeatures & features) const
858 features.require(documentClass().requires());
861 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
862 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
863 LaTeXFeatures::isAvailable("xcolor");
865 switch (features.runparams().flavor) {
866 case OutputParams::LATEX:
868 features.require("ct-dvipost");
869 features.require("dvipost");
870 } else if (xcolorulem) {
871 features.require("ct-xcolor-ulem");
872 features.require("ulem");
873 features.require("xcolor");
875 features.require("ct-none");
878 case OutputParams::PDFLATEX:
880 features.require("ct-xcolor-ulem");
881 features.require("ulem");
882 features.require("xcolor");
883 // improves color handling in PDF output
884 features.require("pdfcolmk");
886 features.require("ct-none");
894 // Floats with 'Here definitely' as default setting.
895 if (float_placement.find('H') != string::npos)
896 features.require("float");
898 // AMS Style is at document level
899 if (use_amsmath == package_on
900 || documentClass().provides("amsmath"))
901 features.require("amsmath");
902 if (use_esint == package_on)
903 features.require("esint");
905 // Document-level line spacing
906 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
907 features.require("setspace");
909 // the bullet shapes are buffer level not paragraph level
910 // so they are tested here
911 for (int i = 0; i < 4; ++i) {
912 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
914 int const font = user_defined_bullet(i).getFont();
916 int const c = user_defined_bullet(i).getCharacter();
922 features.require("latexsym");
924 } else if (font == 1) {
925 features.require("amssymb");
926 } else if (font >= 2 && font <= 5) {
927 features.require("pifont");
931 if (pdfoptions().use_hyperref) {
932 features.require("hyperref");
933 // due to interferences with babel and hyperref, the color package has to
934 // be loaded after hyperref when hyperref is used with the colorlinks
935 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
936 if (pdfoptions().colorlinks)
937 features.require("color");
940 if (language->lang() == "vietnamese")
941 features.require("vietnamese");
942 else if (language->lang() == "japanese")
943 features.require("japanese");
947 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
948 TexRow & texrow) const
950 os << "\\documentclass";
952 DocumentClass const & tclass = documentClass();
954 ostringstream clsoptions; // the document class options.
956 if (tokenPos(tclass.opt_fontsize(),
957 '|', fontsize) >= 0) {
958 // only write if existing in list (and not default)
959 clsoptions << fontsize << "pt,";
962 // custom, A3, B3 and B4 paper sizes need geometry
963 bool nonstandard_papersize = papersize == PAPER_B3
964 || papersize == PAPER_B4
965 || papersize == PAPER_A3
966 || papersize == PAPER_CUSTOM;
971 clsoptions << "a4paper,";
974 clsoptions << "letterpaper,";
977 clsoptions << "a5paper,";
980 clsoptions << "b5paper,";
982 case PAPER_USEXECUTIVE:
983 clsoptions << "executivepaper,";
986 clsoptions << "legalpaper,";
998 if (sides != tclass.sides()) {
1001 clsoptions << "oneside,";
1004 clsoptions << "twoside,";
1010 if (columns != tclass.columns()) {
1012 clsoptions << "twocolumn,";
1014 clsoptions << "onecolumn,";
1018 && orientation == ORIENTATION_LANDSCAPE)
1019 clsoptions << "landscape,";
1021 // language should be a parameter to \documentclass
1022 if (language->babel() == "hebrew"
1023 && default_language->babel() != "hebrew")
1024 // This seems necessary
1025 features.useLanguage(default_language);
1027 ostringstream language_options;
1028 bool const use_babel = features.useBabel();
1030 language_options << features.getLanguages();
1031 if (!language->babel().empty()) {
1032 if (!language_options.str().empty())
1033 language_options << ',';
1034 language_options << language->babel();
1036 // if Vietnamese is used, babel must directly be loaded
1037 // with language options, not in the class options, see
1038 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1039 size_t viet = language_options.str().find("vietnam");
1040 // viet = string::npos when not found
1041 // the same is for all other languages that are not directly supported by
1042 // babel, but where LaTeX-packages add babel support.
1043 // this is currently the case for Latvian, Lithuanian, and Mongolian
1044 size_t latvian = language_options.str().find("latvian");
1045 size_t lithu = language_options.str().find("lithuanian");
1046 size_t mongo = language_options.str().find("mongolian");
1047 // if Japanese is used, babel must directly be loaded
1048 // with language options, not in the class options, see
1049 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1050 size_t japan = language_options.str().find("japanese");
1051 if (lyxrc.language_global_options && !language_options.str().empty()
1052 && viet == string::npos && japan == string::npos
1053 && latvian == string::npos && lithu == string::npos
1054 && mongo == string::npos)
1055 clsoptions << language_options.str() << ',';
1058 // the predefined options from the layout
1059 if (use_default_options && !tclass.options().empty())
1060 clsoptions << tclass.options() << ',';
1062 // the user-defined options
1063 if (!options.empty()) {
1064 clsoptions << options << ',';
1067 string strOptions(clsoptions.str());
1068 if (!strOptions.empty()) {
1069 strOptions = rtrim(strOptions, ",");
1071 os << '[' << from_utf8(strOptions) << ']';
1074 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1076 // end of \documentclass defs
1078 // font selection must be done before loading fontenc.sty
1079 string const fonts =
1080 loadFonts(fontsRoman, fontsSans,
1081 fontsTypewriter, fontsSC, fontsOSF,
1082 fontsSansScale, fontsTypewriterScale);
1083 if (!fonts.empty()) {
1084 os << from_ascii(fonts);
1087 if (fontsDefaultFamily != "default")
1088 os << "\\renewcommand{\\familydefault}{\\"
1089 << from_ascii(fontsDefaultFamily) << "}\n";
1091 // set font encoding
1092 // this one is not per buffer
1093 // for arabic_arabi and farsi we also need to load the LAE and
1095 if (lyxrc.fontenc != "default" && language->lang() != "japanese") {
1096 if (language->lang() == "arabic_arabi"
1097 || language->lang() == "farsi") {
1098 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1099 << ",LFE,LAE]{fontenc}\n";
1102 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1108 // handle inputenc etc.
1109 writeEncodingPreamble(os, features, texrow);
1111 if (!listings_params.empty() || features.isRequired("listings")) {
1112 os << "\\usepackage{listings}\n";
1115 if (!listings_params.empty()) {
1117 // do not test validity because listings_params is
1118 // supposed to be valid
1120 InsetListingsParams(listings_params).separatedParams(true);
1121 // we can't support all packages, but we should load the color package
1122 if (par.find("\\color", 0) != string::npos)
1123 features.require("color");
1124 os << from_utf8(par);
1125 // count the number of newlines
1126 for (size_t i = 0; i < par.size(); ++i)
1132 if (use_geometry || nonstandard_papersize) {
1133 odocstringstream ods;
1134 if (!getGraphicsDriver("geometry").empty())
1135 ods << getGraphicsDriver("geometry");
1136 if (orientation == ORIENTATION_LANDSCAPE)
1137 ods << ",landscape";
1138 switch (papersize) {
1140 if (!paperwidth.empty())
1141 ods << ",paperwidth="
1142 << from_ascii(paperwidth);
1143 if (!paperheight.empty())
1144 ods << ",paperheight="
1145 << from_ascii(paperheight);
1147 case PAPER_USLETTER:
1148 ods << ",letterpaper";
1151 ods << ",legalpaper";
1153 case PAPER_USEXECUTIVE:
1154 ods << ",executivepaper";
1175 // default papersize ie PAPER_DEFAULT
1176 switch (lyxrc.default_papersize) {
1177 case PAPER_DEFAULT: // keep compiler happy
1178 case PAPER_USLETTER:
1179 ods << ",letterpaper";
1182 ods << ",legalpaper";
1184 case PAPER_USEXECUTIVE:
1185 ods << ",executivepaper";
1205 docstring const g_options = trim(ods.str(), ",");
1206 os << "\\usepackage";
1207 if (!g_options.empty())
1208 os << '[' << g_options << ']';
1209 os << "{geometry}\n";
1211 os << "\\geometry{verbose";
1212 if (!topmargin.empty())
1213 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1214 if (!bottommargin.empty())
1215 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1216 if (!leftmargin.empty())
1217 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1218 if (!rightmargin.empty())
1219 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1220 if (!headheight.empty())
1221 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1222 if (!headsep.empty())
1223 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1224 if (!footskip.empty())
1225 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1226 if (!columnsep.empty())
1227 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1230 } else if (orientation == ORIENTATION_LANDSCAPE) {
1231 features.require("papersize");
1234 if (tokenPos(tclass.opt_pagestyle(),
1235 '|', pagestyle) >= 0) {
1236 if (pagestyle == "fancy") {
1237 os << "\\usepackage{fancyhdr}\n";
1240 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1244 // Only if class has a ToC hierarchy
1245 if (tclass.hasTocLevels()) {
1246 if (secnumdepth != tclass.secnumdepth()) {
1247 os << "\\setcounter{secnumdepth}{"
1252 if (tocdepth != tclass.tocdepth()) {
1253 os << "\\setcounter{tocdepth}{"
1260 if (paragraph_separation) {
1261 switch (getDefSkip().kind()) {
1262 case VSpace::SMALLSKIP:
1263 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1265 case VSpace::MEDSKIP:
1266 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1268 case VSpace::BIGSKIP:
1269 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1271 case VSpace::LENGTH:
1272 os << "\\setlength{\\parskip}{"
1273 << from_utf8(getDefSkip().length().asLatexString())
1276 default: // should never happen // Then delete it.
1277 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1282 os << "\\setlength{\\parindent}{0pt}\n";
1286 // Now insert the LyX specific LaTeX commands...
1287 docstring lyxpreamble;
1289 // due to interferences with babel and hyperref, the color package has to
1290 // be loaded (when it is not already loaded) before babel when hyperref
1291 // is used with the colorlinks option, see
1292 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1293 // we decided therefore to load color always before babel, see
1294 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1295 lyxpreamble += from_ascii(features.getColorOptions());
1297 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1299 && (features.isRequired("jurabib")
1300 || features.isRequired("hyperref")
1301 || features.isRequired("vietnamese")
1302 || features.isRequired("japanese") ) ) {
1304 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1305 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1308 // The optional packages;
1309 lyxpreamble += from_ascii(features.getPackages());
1312 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1315 // * Hyperref manual: "Make sure it comes last of your loaded
1316 // packages, to give it a fighting chance of not being over-written,
1317 // since its job is to redefine many LaTeX commands."
1318 // * Email from Heiko Oberdiek: "It is usually better to load babel
1319 // before hyperref. Then hyperref has a chance to detect babel.
1320 // * Has to be loaded before the "LyX specific LaTeX commands" to
1321 // avoid errors with algorithm floats.
1322 // use hyperref explicitely when it is required
1323 if (features.isRequired("hyperref")) {
1324 odocstringstream oss;
1325 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1326 lyxpreamble += oss.str();
1329 // Will be surrounded by \makeatletter and \makeatother when needed
1330 docstring atlyxpreamble;
1332 // Some macros LyX will need
1333 docstring tmppreamble(from_ascii(features.getMacros()));
1335 if (!tmppreamble.empty())
1336 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1337 "LyX specific LaTeX commands.\n"
1338 + tmppreamble + '\n';
1340 // the text class specific preamble
1341 tmppreamble = features.getTClassPreamble();
1342 if (!tmppreamble.empty())
1343 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1344 "Textclass specific LaTeX commands.\n"
1345 + tmppreamble + '\n';
1347 /* the user-defined preamble */
1348 if (!preamble.empty())
1350 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1351 "User specified LaTeX commands.\n"
1352 + from_utf8(preamble) + '\n';
1354 // subfig loads internally the LaTeX package "caption". As
1355 // caption is a very popular package, users will load it in
1356 // the preamble. Therefore we must load subfig behind the
1357 // user-defined preamble and check if the caption package was
1358 // loaded or not. For the case that caption is loaded before
1359 // subfig, there is the subfig option "caption=false". This
1360 // option also works when a koma-script class is used and
1361 // koma's own caption commands are used instead of caption. We
1362 // use \PassOptionsToPackage here because the user could have
1363 // already loaded subfig in the preamble.
1364 if (features.isRequired("subfig")) {
1365 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1366 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1367 "\\usepackage{subfig}\n";
1370 // Itemize bullet settings need to be last in case the user
1371 // defines their own bullets that use a package included
1372 // in the user-defined preamble -- ARRae
1373 // Actually it has to be done much later than that
1374 // since some packages like frenchb make modifications
1375 // at \begin{document} time -- JMarc
1376 docstring bullets_def;
1377 for (int i = 0; i < 4; ++i) {
1378 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1379 if (bullets_def.empty())
1380 bullets_def += "\\AtBeginDocument{\n";
1381 bullets_def += " \\def\\labelitemi";
1383 // `i' is one less than the item to modify
1390 bullets_def += "ii";
1396 bullets_def += '{' +
1397 user_defined_bullet(i).getText()
1402 if (!bullets_def.empty())
1403 atlyxpreamble += bullets_def + "}\n\n";
1405 if (atlyxpreamble.find(from_ascii("@")) != docstring::npos)
1406 lyxpreamble += "\n\\makeatletter\n"
1407 + atlyxpreamble + "\\makeatother\n\n";
1409 lyxpreamble += '\n' + atlyxpreamble;
1411 // We try to load babel late, in case it interferes with other packages.
1412 // Jurabib and Hyperref have to be called after babel, though.
1413 if (use_babel && !features.isRequired("jurabib")
1414 && !features.isRequired("hyperref")
1415 && !features.isRequired("vietnamese")
1416 && !features.isRequired("japanese")) {
1418 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1419 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1422 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1423 if (!i18npreamble.empty())
1424 lyxpreamble += i18npreamble + '\n';
1427 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1428 for (int j = 0; j != nlines; ++j) {
1437 void BufferParams::useClassDefaults()
1439 DocumentClass const & tclass = documentClass();
1441 sides = tclass.sides();
1442 columns = tclass.columns();
1443 pagestyle = tclass.pagestyle();
1444 use_default_options = true;
1445 // Only if class has a ToC hierarchy
1446 if (tclass.hasTocLevels()) {
1447 secnumdepth = tclass.secnumdepth();
1448 tocdepth = tclass.tocdepth();
1453 bool BufferParams::hasClassDefaults() const
1455 DocumentClass const & tclass = documentClass();
1457 return sides == tclass.sides()
1458 && columns == tclass.columns()
1459 && pagestyle == tclass.pagestyle()
1460 && use_default_options
1461 && secnumdepth == tclass.secnumdepth()
1462 && tocdepth == tclass.tocdepth();
1466 DocumentClass const & BufferParams::documentClass() const
1472 DocumentClass const * BufferParams::documentClassPtr() const {
1477 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1478 // evil, but this function is evil
1479 doc_class_ = const_cast<DocumentClass *>(tc);
1483 bool BufferParams::setBaseClass(string const & classname)
1485 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1486 LayoutFileList & bcl = LayoutFileList::get();
1487 if (!bcl.haveClass(classname)) {
1489 bformat(_("The document class %1$s could not be found. "
1490 "A default textclass with default layouts will be used. "
1491 "LyX might not be able to produce output unless a correct "
1492 "textclass is selected from the document settings dialog."),
1493 from_utf8(classname));
1494 frontend::Alert::error(_("Document class not found"), s);
1495 bcl.addEmptyClass(classname);
1498 bool const success = bcl[classname].load();
1501 bformat(_("The document class %1$s could not be loaded."),
1502 from_utf8(classname));
1503 frontend::Alert::error(_("Could not load class"), s);
1507 pimpl_->baseClass_ = classname;
1508 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1513 LayoutFile const * BufferParams::baseClass() const
1515 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1516 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1522 LayoutFileIndex const & BufferParams::baseClassID() const
1524 return pimpl_->baseClass_;
1528 void BufferParams::makeDocumentClass()
1533 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1535 if (!local_layout.empty()) {
1536 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1537 docstring const msg = _("Error reading internal layout information");
1538 frontend::Alert::warning(_("Read Error"), msg);
1543 bool BufferParams::moduleCanBeAdded(string const & modName) const
1545 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1549 bool BufferParams::addLayoutModule(string const & modName)
1551 LayoutModuleList::const_iterator it = layoutModules_.begin();
1552 LayoutModuleList::const_iterator end = layoutModules_.end();
1553 for (; it != end; it++)
1556 layoutModules_.push_back(modName);
1561 Font const BufferParams::getFont() const
1563 FontInfo f = documentClass().defaultfont();
1564 if (fontsDefaultFamily == "rmdefault")
1565 f.setFamily(ROMAN_FAMILY);
1566 else if (fontsDefaultFamily == "sfdefault")
1567 f.setFamily(SANS_FAMILY);
1568 else if (fontsDefaultFamily == "ttdefault")
1569 f.setFamily(TYPEWRITER_FAMILY);
1570 return Font(f, language);
1574 void BufferParams::readPreamble(Lexer & lex)
1576 if (lex.getString() != "\\begin_preamble")
1577 lyxerr << "Error (BufferParams::readPreamble):"
1578 "consistency check failed." << endl;
1580 preamble = lex.getLongString("\\end_preamble");
1584 void BufferParams::readLocalLayout(Lexer & lex)
1586 if (lex.getString() != "\\begin_local_layout")
1587 lyxerr << "Error (BufferParams::readLocalLayout):"
1588 "consistency check failed." << endl;
1590 local_layout = lex.getLongString("\\end_local_layout");
1594 void BufferParams::readLanguage(Lexer & lex)
1596 if (!lex.next()) return;
1598 string const tmptok = lex.getString();
1600 // check if tmptok is part of tex_babel in tex-defs.h
1601 language = languages.getLanguage(tmptok);
1603 // Language tmptok was not found
1604 language = default_language;
1605 lyxerr << "Warning: Setting language `"
1606 << tmptok << "' to `" << language->lang()
1612 void BufferParams::readGraphicsDriver(Lexer & lex)
1617 string const tmptok = lex.getString();
1618 // check if tmptok is part of tex_graphics in tex_defs.h
1621 string const test = tex_graphics[n++];
1623 if (test == tmptok) {
1624 graphicsDriver = tmptok;
1629 "Warning: graphics driver `$$Token' not recognized!\n"
1630 " Setting graphics driver to `default'.\n");
1631 graphicsDriver = "default";
1638 void BufferParams::readBullets(Lexer & lex)
1643 int const index = lex.getInteger();
1645 int temp_int = lex.getInteger();
1646 user_defined_bullet(index).setFont(temp_int);
1647 temp_bullet(index).setFont(temp_int);
1649 user_defined_bullet(index).setCharacter(temp_int);
1650 temp_bullet(index).setCharacter(temp_int);
1652 user_defined_bullet(index).setSize(temp_int);
1653 temp_bullet(index).setSize(temp_int);
1657 void BufferParams::readBulletsLaTeX(Lexer & lex)
1659 // The bullet class should be able to read this.
1662 int const index = lex.getInteger();
1664 docstring const temp_str = lex.getDocString();
1666 user_defined_bullet(index).setText(temp_str);
1667 temp_bullet(index).setText(temp_str);
1671 void BufferParams::readModules(Lexer & lex)
1673 if (!lex.eatLine()) {
1674 lyxerr << "Error (BufferParams::readModules):"
1675 "Unexpected end of input." << endl;
1679 string mod = lex.getString();
1680 if (mod == "\\end_modules")
1682 addLayoutModule(mod);
1688 void BufferParams::readRemovedModules(Lexer & lex)
1690 if (!lex.eatLine()) {
1691 lyxerr << "Error (BufferParams::readRemovedModules):"
1692 "Unexpected end of input." << endl;
1696 string mod = lex.getString();
1697 if (mod == "\\end_removed_modules")
1699 removedModules_.push_back(mod);
1702 // now we want to remove any removed modules that were previously
1703 // added. normally, that will be because default modules were added in
1704 // setBaseClass(), which gets called when \textclass is read at the
1705 // start of the read.
1706 list<string>::const_iterator rit = removedModules_.begin();
1707 list<string>::const_iterator const ren = removedModules_.end();
1708 for (; rit != ren; rit++) {
1709 LayoutModuleList::iterator const mit = layoutModules_.begin();
1710 LayoutModuleList::iterator const men = layoutModules_.end();
1711 LayoutModuleList::iterator found = find(mit, men, *rit);
1714 layoutModules_.erase(found);
1719 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1721 char real_papersize = papersize;
1722 if (real_papersize == PAPER_DEFAULT)
1723 real_papersize = lyxrc.default_papersize;
1725 switch (real_papersize) {
1727 // could be anything, so don't guess
1729 case PAPER_CUSTOM: {
1730 if (purpose == XDVI && !paperwidth.empty() &&
1731 !paperheight.empty()) {
1732 // heightxwidth<unit>
1733 string first = paperwidth;
1734 string second = paperheight;
1735 if (orientation == ORIENTATION_LANDSCAPE)
1738 return first.erase(first.length() - 2)
1750 // dvips and dvipdfm do not know this
1751 if (purpose == DVIPS || purpose == DVIPDFM)
1755 // dvipdfm does not know this
1756 if (purpose == DVIPDFM)
1760 // dvipdfm does not know this
1761 if (purpose == DVIPDFM)
1764 case PAPER_USEXECUTIVE:
1765 // dvipdfm does not know this
1766 if (purpose == DVIPDFM)
1771 case PAPER_USLETTER:
1773 if (purpose == XDVI)
1780 string const BufferParams::dvips_options() const
1785 && papersize == PAPER_CUSTOM
1786 && !lyxrc.print_paper_dimension_flag.empty()
1787 && !paperwidth.empty()
1788 && !paperheight.empty()) {
1789 // using a custom papersize
1790 result = lyxrc.print_paper_dimension_flag;
1791 result += ' ' + paperwidth;
1792 result += ',' + paperheight;
1794 string const paper_option = paperSizeName(DVIPS);
1795 if (!paper_option.empty() && (paper_option != "letter" ||
1796 orientation != ORIENTATION_LANDSCAPE)) {
1797 // dvips won't accept -t letter -t landscape.
1798 // In all other cases, include the paper size
1800 result = lyxrc.print_paper_flag;
1801 result += ' ' + paper_option;
1804 if (orientation == ORIENTATION_LANDSCAPE &&
1805 papersize != PAPER_CUSTOM)
1806 result += ' ' + lyxrc.print_landscape_flag;
1811 string BufferParams::babelCall(string const & lang_opts) const
1813 string lang_pack = lyxrc.language_package;
1814 if (lang_pack != "\\usepackage{babel}")
1816 // suppress the babel call when there is no babel language defined
1817 // for the document language in the lib/languages file and if no
1818 // other languages are used (lang_opts is then empty)
1819 if (lang_opts.empty())
1821 // If Vietnamese is used, babel must directly be loaded with the
1822 // language options, see
1823 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1824 size_t viet = lang_opts.find("vietnam");
1825 // viet = string::npos when not found
1826 // the same is for all other languages that are not directly supported by
1827 // babel, but where LaTeX-packages add babel support.
1828 // this is currently the case for Latvian, Lithuanian, and Mongolian
1829 size_t latvian = lang_opts.find("latvian");
1830 size_t lithu = lang_opts.find("lithuanian");
1831 size_t mongo = lang_opts.find("mongolian");
1832 // If Japanese is used, babel must directly be loaded with the
1833 // language options, see
1834 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1835 size_t japan = lang_opts.find("japanese");
1836 if (!lyxrc.language_global_options || viet != string::npos
1837 || japan != string::npos || latvian != string::npos
1838 || lithu != string::npos || mongo != string::npos)
1839 return "\\usepackage[" + lang_opts + "]{babel}";
1844 docstring BufferParams::getGraphicsDriver(string const & package) const
1848 if (package == "geometry") {
1849 if (graphicsDriver == "dvips"
1850 || graphicsDriver == "dvipdfm"
1851 || graphicsDriver == "pdftex"
1852 || graphicsDriver == "vtex")
1853 result = from_ascii(graphicsDriver);
1854 else if (graphicsDriver == "dvipdfmx")
1855 result = from_ascii("dvipdfm");
1862 void BufferParams::writeEncodingPreamble(odocstream & os,
1863 LaTeXFeatures & features, TexRow & texrow) const
1865 if (inputenc == "auto") {
1866 string const doc_encoding =
1867 language->encoding()->latexName();
1868 Encoding::Package const package =
1869 language->encoding()->package();
1871 // Create a list with all the input encodings used
1873 set<string> encodings =
1874 features.getEncodingSet(doc_encoding);
1876 // If the "japanese" package (i.e. pLaTeX) is used,
1877 // inputenc must be omitted.
1878 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1879 if (package == Encoding::japanese)
1880 features.require("japanese");
1882 if ((!encodings.empty() || package == Encoding::inputenc)
1883 && !features.isRequired("japanese")) {
1884 os << "\\usepackage[";
1885 set<string>::const_iterator it = encodings.begin();
1886 set<string>::const_iterator const end = encodings.end();
1888 os << from_ascii(*it);
1891 for (; it != end; ++it)
1892 os << ',' << from_ascii(*it);
1893 if (package == Encoding::inputenc) {
1894 if (!encodings.empty())
1896 os << from_ascii(doc_encoding);
1898 os << "]{inputenc}\n";
1901 if (package == Encoding::CJK || features.mustProvide("CJK")) {
1902 if (language->encoding()->name() == "utf8-cjk"
1903 && LaTeXFeatures::isAvailable("CJKutf8"))
1904 os << "\\usepackage{CJKutf8}\n";
1906 os << "\\usepackage{CJK}\n";
1909 } else if (inputenc != "default") {
1910 switch (encoding().package()) {
1911 case Encoding::none:
1912 case Encoding::japanese:
1914 case Encoding::inputenc:
1915 // do not load inputenc if japanese is used
1916 if (features.isRequired("japanese"))
1918 os << "\\usepackage[" << from_ascii(inputenc)
1923 if (encoding().name() == "utf8-cjk"
1924 && LaTeXFeatures::isAvailable("CJKutf8"))
1925 os << "\\usepackage{CJKutf8}\n";
1927 os << "\\usepackage{CJK}\n";
1933 // The encoding "armscii8" (for Armenian) is only available when
1934 // the package "armtex" is loaded.
1935 if (language->encoding()->latexName() == "armscii8"
1936 || inputenc == "armscii8") {
1937 os << "\\usepackage{armtex}\n";
1943 string const BufferParams::loadFonts(string const & rm,
1944 string const & sf, string const & tt,
1945 bool const & sc, bool const & osf,
1946 int const & sfscale, int const & ttscale) const
1948 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1949 several packages have been replaced by others, that might not
1950 be installed on every system. We have to take care for that
1951 (see psnfss.pdf). We try to support all psnfss fonts as well
1952 as the fonts that have become de facto standard in the LaTeX
1953 world (e.g. Latin Modern). We do not support obsolete fonts
1954 (like PSLatex). In general, it should be possible to mix any
1955 rm font with any sf or tt font, respectively. (JSpitzm)
1957 -- separate math fonts.
1960 if (rm == "default" && sf == "default" && tt == "default")
1967 // Computer Modern (must be explicitely selectable -- there might be classes
1968 // that define a different default font!
1970 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1971 // osf for Computer Modern needs eco.sty
1973 os << "\\usepackage{eco}\n";
1975 // Latin Modern Roman
1976 else if (rm == "lmodern")
1977 os << "\\usepackage{lmodern}\n";
1979 else if (rm == "ae") {
1980 // not needed when using OT1 font encoding.
1981 if (lyxrc.fontenc != "default")
1982 os << "\\usepackage{ae,aecompl}\n";
1985 else if (rm == "times") {
1986 // try to load the best available package
1987 if (LaTeXFeatures::isAvailable("mathptmx"))
1988 os << "\\usepackage{mathptmx}\n";
1989 else if (LaTeXFeatures::isAvailable("mathptm"))
1990 os << "\\usepackage{mathptm}\n";
1992 os << "\\usepackage{times}\n";
1995 else if (rm == "palatino") {
1996 // try to load the best available package
1997 if (LaTeXFeatures::isAvailable("mathpazo")) {
1998 os << "\\usepackage";
2004 // "osf" includes "sc"!
2008 os << "{mathpazo}\n";
2010 else if (LaTeXFeatures::isAvailable("mathpple"))
2011 os << "\\usepackage{mathpple}\n";
2013 os << "\\usepackage{palatino}\n";
2016 else if (rm == "utopia") {
2017 // fourier supersedes utopia.sty, but does
2018 // not work with OT1 encoding.
2019 if (LaTeXFeatures::isAvailable("fourier")
2020 && lyxrc.fontenc != "default") {
2021 os << "\\usepackage";
2032 os << "{fourier}\n";
2035 os << "\\usepackage{utopia}\n";
2037 // Bera (complete fontset)
2038 else if (rm == "bera" && sf == "default" && tt == "default")
2039 os << "\\usepackage{bera}\n";
2041 else if (rm != "default")
2042 os << "\\usepackage" << "{" << rm << "}\n";
2045 // Helvetica, Bera Sans
2046 if (sf == "helvet" || sf == "berasans") {
2048 os << "\\usepackage[scaled=" << float(sfscale) / 100
2049 << "]{" << sf << "}\n";
2051 os << "\\usepackage{" << sf << "}\n";
2054 else if (sf == "avant")
2055 os << "\\usepackage{" << sf << "}\n";
2056 // Computer Modern, Latin Modern, CM Bright
2057 else if (sf != "default")
2058 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2060 // monospaced/typewriter
2061 // Courier, LuxiMono
2062 if (tt == "luximono" || tt == "beramono") {
2064 os << "\\usepackage[scaled=" << float(ttscale) / 100
2065 << "]{" << tt << "}\n";
2067 os << "\\usepackage{" << tt << "}\n";
2070 else if (tt == "courier" )
2071 os << "\\usepackage{" << tt << "}\n";
2072 // Computer Modern, Latin Modern, CM Bright
2073 else if (tt != "default")
2074 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2080 Encoding const & BufferParams::encoding() const
2082 if (inputenc == "auto" || inputenc == "default")
2083 return *language->encoding();
2084 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2087 LYXERR0("Unknown inputenc value `" << inputenc
2088 << "'. Using `auto' instead.");
2089 return *language->encoding();
2093 CiteEngine BufferParams::citeEngine() const
2095 // FIXME the class should provide the numerical/
2096 // authoryear choice
2097 if (documentClass().provides("natbib")
2098 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2099 return ENGINE_NATBIB_AUTHORYEAR;
2100 return cite_engine_;
2104 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2106 cite_engine_ = cite_engine;