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 (!tclass.provides("geometry")
1133 && (use_geometry || nonstandard_papersize)) {
1134 odocstringstream ods;
1135 if (!getGraphicsDriver("geometry").empty())
1136 ods << getGraphicsDriver("geometry");
1137 if (orientation == ORIENTATION_LANDSCAPE)
1138 ods << ",landscape";
1139 switch (papersize) {
1141 if (!paperwidth.empty())
1142 ods << ",paperwidth="
1143 << from_ascii(paperwidth);
1144 if (!paperheight.empty())
1145 ods << ",paperheight="
1146 << from_ascii(paperheight);
1148 case PAPER_USLETTER:
1149 ods << ",letterpaper";
1152 ods << ",legalpaper";
1154 case PAPER_USEXECUTIVE:
1155 ods << ",executivepaper";
1176 // default papersize ie PAPER_DEFAULT
1177 switch (lyxrc.default_papersize) {
1178 case PAPER_DEFAULT: // keep compiler happy
1179 case PAPER_USLETTER:
1180 ods << ",letterpaper";
1183 ods << ",legalpaper";
1185 case PAPER_USEXECUTIVE:
1186 ods << ",executivepaper";
1206 docstring const g_options = trim(ods.str(), ",");
1207 os << "\\usepackage";
1208 if (!g_options.empty())
1209 os << '[' << g_options << ']';
1210 os << "{geometry}\n";
1212 os << "\\geometry{verbose";
1213 if (!topmargin.empty())
1214 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1215 if (!bottommargin.empty())
1216 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1217 if (!leftmargin.empty())
1218 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1219 if (!rightmargin.empty())
1220 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1221 if (!headheight.empty())
1222 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1223 if (!headsep.empty())
1224 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1225 if (!footskip.empty())
1226 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1227 if (!columnsep.empty())
1228 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1231 } else if (orientation == ORIENTATION_LANDSCAPE) {
1232 features.require("papersize");
1235 if (tokenPos(tclass.opt_pagestyle(),
1236 '|', pagestyle) >= 0) {
1237 if (pagestyle == "fancy") {
1238 os << "\\usepackage{fancyhdr}\n";
1241 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1245 // Only if class has a ToC hierarchy
1246 if (tclass.hasTocLevels()) {
1247 if (secnumdepth != tclass.secnumdepth()) {
1248 os << "\\setcounter{secnumdepth}{"
1253 if (tocdepth != tclass.tocdepth()) {
1254 os << "\\setcounter{tocdepth}{"
1261 if (paragraph_separation) {
1262 switch (getDefSkip().kind()) {
1263 case VSpace::SMALLSKIP:
1264 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1266 case VSpace::MEDSKIP:
1267 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1269 case VSpace::BIGSKIP:
1270 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1272 case VSpace::LENGTH:
1273 os << "\\setlength{\\parskip}{"
1274 << from_utf8(getDefSkip().length().asLatexString())
1277 default: // should never happen // Then delete it.
1278 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1283 os << "\\setlength{\\parindent}{0pt}\n";
1287 // Now insert the LyX specific LaTeX commands...
1288 docstring lyxpreamble;
1290 // due to interferences with babel and hyperref, the color package has to
1291 // be loaded (when it is not already loaded) before babel when hyperref
1292 // is used with the colorlinks option, see
1293 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1294 // we decided therefore to load color always before babel, see
1295 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1296 lyxpreamble += from_ascii(features.getColorOptions());
1298 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1300 && (features.isRequired("jurabib")
1301 || features.isRequired("hyperref")
1302 || features.isRequired("vietnamese")
1303 || features.isRequired("japanese") ) ) {
1305 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1306 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1309 // The optional packages;
1310 lyxpreamble += from_ascii(features.getPackages());
1313 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1316 // * Hyperref manual: "Make sure it comes last of your loaded
1317 // packages, to give it a fighting chance of not being over-written,
1318 // since its job is to redefine many LaTeX commands."
1319 // * Email from Heiko Oberdiek: "It is usually better to load babel
1320 // before hyperref. Then hyperref has a chance to detect babel.
1321 // * Has to be loaded before the "LyX specific LaTeX commands" to
1322 // avoid errors with algorithm floats.
1323 // use hyperref explicitely when it is required
1324 if (features.isRequired("hyperref")) {
1325 odocstringstream oss;
1326 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1327 lyxpreamble += oss.str();
1330 // Will be surrounded by \makeatletter and \makeatother when needed
1331 docstring atlyxpreamble;
1333 // Some macros LyX will need
1334 docstring tmppreamble(from_ascii(features.getMacros()));
1336 if (!tmppreamble.empty())
1337 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1338 "LyX specific LaTeX commands.\n"
1339 + tmppreamble + '\n';
1341 // the text class specific preamble
1342 tmppreamble = features.getTClassPreamble();
1343 if (!tmppreamble.empty())
1344 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1345 "Textclass specific LaTeX commands.\n"
1346 + tmppreamble + '\n';
1348 /* the user-defined preamble */
1349 if (!preamble.empty())
1351 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1352 "User specified LaTeX commands.\n"
1353 + from_utf8(preamble) + '\n';
1355 // subfig loads internally the LaTeX package "caption". As
1356 // caption is a very popular package, users will load it in
1357 // the preamble. Therefore we must load subfig behind the
1358 // user-defined preamble and check if the caption package was
1359 // loaded or not. For the case that caption is loaded before
1360 // subfig, there is the subfig option "caption=false". This
1361 // option also works when a koma-script class is used and
1362 // koma's own caption commands are used instead of caption. We
1363 // use \PassOptionsToPackage here because the user could have
1364 // already loaded subfig in the preamble.
1365 if (features.isRequired("subfig")) {
1366 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1367 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1368 "\\usepackage{subfig}\n";
1371 // Itemize bullet settings need to be last in case the user
1372 // defines their own bullets that use a package included
1373 // in the user-defined preamble -- ARRae
1374 // Actually it has to be done much later than that
1375 // since some packages like frenchb make modifications
1376 // at \begin{document} time -- JMarc
1377 docstring bullets_def;
1378 for (int i = 0; i < 4; ++i) {
1379 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1380 if (bullets_def.empty())
1381 bullets_def += "\\AtBeginDocument{\n";
1382 bullets_def += " \\def\\labelitemi";
1384 // `i' is one less than the item to modify
1391 bullets_def += "ii";
1397 bullets_def += '{' +
1398 user_defined_bullet(i).getText()
1403 if (!bullets_def.empty())
1404 atlyxpreamble += bullets_def + "}\n\n";
1406 if (atlyxpreamble.find(from_ascii("@")) != docstring::npos)
1407 lyxpreamble += "\n\\makeatletter\n"
1408 + atlyxpreamble + "\\makeatother\n\n";
1410 lyxpreamble += '\n' + atlyxpreamble;
1412 // We try to load babel late, in case it interferes with other packages.
1413 // Jurabib and Hyperref have to be called after babel, though.
1414 if (use_babel && !features.isRequired("jurabib")
1415 && !features.isRequired("hyperref")
1416 && !features.isRequired("vietnamese")
1417 && !features.isRequired("japanese")) {
1419 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1420 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1423 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1424 if (!i18npreamble.empty())
1425 lyxpreamble += i18npreamble + '\n';
1428 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1429 for (int j = 0; j != nlines; ++j) {
1438 void BufferParams::useClassDefaults()
1440 DocumentClass const & tclass = documentClass();
1442 sides = tclass.sides();
1443 columns = tclass.columns();
1444 pagestyle = tclass.pagestyle();
1445 use_default_options = true;
1446 // Only if class has a ToC hierarchy
1447 if (tclass.hasTocLevels()) {
1448 secnumdepth = tclass.secnumdepth();
1449 tocdepth = tclass.tocdepth();
1454 bool BufferParams::hasClassDefaults() const
1456 DocumentClass const & tclass = documentClass();
1458 return sides == tclass.sides()
1459 && columns == tclass.columns()
1460 && pagestyle == tclass.pagestyle()
1461 && use_default_options
1462 && secnumdepth == tclass.secnumdepth()
1463 && tocdepth == tclass.tocdepth();
1467 DocumentClass const & BufferParams::documentClass() const
1473 DocumentClass const * BufferParams::documentClassPtr() const {
1478 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1479 // evil, but this function is evil
1480 doc_class_ = const_cast<DocumentClass *>(tc);
1484 bool BufferParams::setBaseClass(string const & classname)
1486 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1487 LayoutFileList & bcl = LayoutFileList::get();
1488 if (!bcl.haveClass(classname)) {
1490 bformat(_("The document class %1$s could not be found. "
1491 "A default textclass with default layouts will be used. "
1492 "LyX might not be able to produce output unless a correct "
1493 "textclass is selected from the document settings dialog."),
1494 from_utf8(classname));
1495 frontend::Alert::error(_("Document class not found"), s);
1496 bcl.addEmptyClass(classname);
1499 bool const success = bcl[classname].load();
1502 bformat(_("The document class %1$s could not be loaded."),
1503 from_utf8(classname));
1504 frontend::Alert::error(_("Could not load class"), s);
1508 pimpl_->baseClass_ = classname;
1509 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1514 LayoutFile const * BufferParams::baseClass() const
1516 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1517 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1523 LayoutFileIndex const & BufferParams::baseClassID() const
1525 return pimpl_->baseClass_;
1529 void BufferParams::makeDocumentClass()
1534 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1536 if (!local_layout.empty()) {
1537 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1538 docstring const msg = _("Error reading internal layout information");
1539 frontend::Alert::warning(_("Read Error"), msg);
1544 bool BufferParams::moduleCanBeAdded(string const & modName) const
1546 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1550 bool BufferParams::addLayoutModule(string const & modName)
1552 LayoutModuleList::const_iterator it = layoutModules_.begin();
1553 LayoutModuleList::const_iterator end = layoutModules_.end();
1554 for (; it != end; it++)
1557 layoutModules_.push_back(modName);
1562 Font const BufferParams::getFont() const
1564 FontInfo f = documentClass().defaultfont();
1565 if (fontsDefaultFamily == "rmdefault")
1566 f.setFamily(ROMAN_FAMILY);
1567 else if (fontsDefaultFamily == "sfdefault")
1568 f.setFamily(SANS_FAMILY);
1569 else if (fontsDefaultFamily == "ttdefault")
1570 f.setFamily(TYPEWRITER_FAMILY);
1571 return Font(f, language);
1575 void BufferParams::readPreamble(Lexer & lex)
1577 if (lex.getString() != "\\begin_preamble")
1578 lyxerr << "Error (BufferParams::readPreamble):"
1579 "consistency check failed." << endl;
1581 preamble = lex.getLongString("\\end_preamble");
1585 void BufferParams::readLocalLayout(Lexer & lex)
1587 if (lex.getString() != "\\begin_local_layout")
1588 lyxerr << "Error (BufferParams::readLocalLayout):"
1589 "consistency check failed." << endl;
1591 local_layout = lex.getLongString("\\end_local_layout");
1595 void BufferParams::readLanguage(Lexer & lex)
1597 if (!lex.next()) return;
1599 string const tmptok = lex.getString();
1601 // check if tmptok is part of tex_babel in tex-defs.h
1602 language = languages.getLanguage(tmptok);
1604 // Language tmptok was not found
1605 language = default_language;
1606 lyxerr << "Warning: Setting language `"
1607 << tmptok << "' to `" << language->lang()
1613 void BufferParams::readGraphicsDriver(Lexer & lex)
1618 string const tmptok = lex.getString();
1619 // check if tmptok is part of tex_graphics in tex_defs.h
1622 string const test = tex_graphics[n++];
1624 if (test == tmptok) {
1625 graphicsDriver = tmptok;
1630 "Warning: graphics driver `$$Token' not recognized!\n"
1631 " Setting graphics driver to `default'.\n");
1632 graphicsDriver = "default";
1639 void BufferParams::readBullets(Lexer & lex)
1644 int const index = lex.getInteger();
1646 int temp_int = lex.getInteger();
1647 user_defined_bullet(index).setFont(temp_int);
1648 temp_bullet(index).setFont(temp_int);
1650 user_defined_bullet(index).setCharacter(temp_int);
1651 temp_bullet(index).setCharacter(temp_int);
1653 user_defined_bullet(index).setSize(temp_int);
1654 temp_bullet(index).setSize(temp_int);
1658 void BufferParams::readBulletsLaTeX(Lexer & lex)
1660 // The bullet class should be able to read this.
1663 int const index = lex.getInteger();
1665 docstring const temp_str = lex.getDocString();
1667 user_defined_bullet(index).setText(temp_str);
1668 temp_bullet(index).setText(temp_str);
1672 void BufferParams::readModules(Lexer & lex)
1674 if (!lex.eatLine()) {
1675 lyxerr << "Error (BufferParams::readModules):"
1676 "Unexpected end of input." << endl;
1680 string mod = lex.getString();
1681 if (mod == "\\end_modules")
1683 addLayoutModule(mod);
1689 void BufferParams::readRemovedModules(Lexer & lex)
1691 if (!lex.eatLine()) {
1692 lyxerr << "Error (BufferParams::readRemovedModules):"
1693 "Unexpected end of input." << endl;
1697 string mod = lex.getString();
1698 if (mod == "\\end_removed_modules")
1700 removedModules_.push_back(mod);
1703 // now we want to remove any removed modules that were previously
1704 // added. normally, that will be because default modules were added in
1705 // setBaseClass(), which gets called when \textclass is read at the
1706 // start of the read.
1707 list<string>::const_iterator rit = removedModules_.begin();
1708 list<string>::const_iterator const ren = removedModules_.end();
1709 for (; rit != ren; rit++) {
1710 LayoutModuleList::iterator const mit = layoutModules_.begin();
1711 LayoutModuleList::iterator const men = layoutModules_.end();
1712 LayoutModuleList::iterator found = find(mit, men, *rit);
1715 layoutModules_.erase(found);
1720 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1722 char real_papersize = papersize;
1723 if (real_papersize == PAPER_DEFAULT)
1724 real_papersize = lyxrc.default_papersize;
1726 switch (real_papersize) {
1728 // could be anything, so don't guess
1730 case PAPER_CUSTOM: {
1731 if (purpose == XDVI && !paperwidth.empty() &&
1732 !paperheight.empty()) {
1733 // heightxwidth<unit>
1734 string first = paperwidth;
1735 string second = paperheight;
1736 if (orientation == ORIENTATION_LANDSCAPE)
1739 return first.erase(first.length() - 2)
1751 // dvips and dvipdfm do not know this
1752 if (purpose == DVIPS || purpose == DVIPDFM)
1756 // dvipdfm does not know this
1757 if (purpose == DVIPDFM)
1761 // dvipdfm does not know this
1762 if (purpose == DVIPDFM)
1765 case PAPER_USEXECUTIVE:
1766 // dvipdfm does not know this
1767 if (purpose == DVIPDFM)
1772 case PAPER_USLETTER:
1774 if (purpose == XDVI)
1781 string const BufferParams::dvips_options() const
1786 && papersize == PAPER_CUSTOM
1787 && !lyxrc.print_paper_dimension_flag.empty()
1788 && !paperwidth.empty()
1789 && !paperheight.empty()) {
1790 // using a custom papersize
1791 result = lyxrc.print_paper_dimension_flag;
1792 result += ' ' + paperwidth;
1793 result += ',' + paperheight;
1795 string const paper_option = paperSizeName(DVIPS);
1796 if (!paper_option.empty() && (paper_option != "letter" ||
1797 orientation != ORIENTATION_LANDSCAPE)) {
1798 // dvips won't accept -t letter -t landscape.
1799 // In all other cases, include the paper size
1801 result = lyxrc.print_paper_flag;
1802 result += ' ' + paper_option;
1805 if (orientation == ORIENTATION_LANDSCAPE &&
1806 papersize != PAPER_CUSTOM)
1807 result += ' ' + lyxrc.print_landscape_flag;
1812 string BufferParams::babelCall(string const & lang_opts) const
1814 string lang_pack = lyxrc.language_package;
1815 if (lang_pack != "\\usepackage{babel}")
1817 // suppress the babel call when there is no babel language defined
1818 // for the document language in the lib/languages file and if no
1819 // other languages are used (lang_opts is then empty)
1820 if (lang_opts.empty())
1822 // If Vietnamese is used, babel must directly be loaded with the
1823 // language options, see
1824 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1825 size_t viet = lang_opts.find("vietnam");
1826 // viet = string::npos when not found
1827 // the same is for all other languages that are not directly supported by
1828 // babel, but where LaTeX-packages add babel support.
1829 // this is currently the case for Latvian, Lithuanian, and Mongolian
1830 size_t latvian = lang_opts.find("latvian");
1831 size_t lithu = lang_opts.find("lithuanian");
1832 size_t mongo = lang_opts.find("mongolian");
1833 // If Japanese is used, babel must directly be loaded with the
1834 // language options, see
1835 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1836 size_t japan = lang_opts.find("japanese");
1837 if (!lyxrc.language_global_options || viet != string::npos
1838 || japan != string::npos || latvian != string::npos
1839 || lithu != string::npos || mongo != string::npos)
1840 return "\\usepackage[" + lang_opts + "]{babel}";
1845 docstring BufferParams::getGraphicsDriver(string const & package) const
1849 if (package == "geometry") {
1850 if (graphicsDriver == "dvips"
1851 || graphicsDriver == "dvipdfm"
1852 || graphicsDriver == "pdftex"
1853 || graphicsDriver == "vtex")
1854 result = from_ascii(graphicsDriver);
1855 else if (graphicsDriver == "dvipdfmx")
1856 result = from_ascii("dvipdfm");
1863 void BufferParams::writeEncodingPreamble(odocstream & os,
1864 LaTeXFeatures & features, TexRow & texrow) const
1866 if (inputenc == "auto") {
1867 string const doc_encoding =
1868 language->encoding()->latexName();
1869 Encoding::Package const package =
1870 language->encoding()->package();
1872 // Create a list with all the input encodings used
1874 set<string> encodings =
1875 features.getEncodingSet(doc_encoding);
1877 // If the "japanese" package (i.e. pLaTeX) is used,
1878 // inputenc must be omitted.
1879 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1880 if (package == Encoding::japanese)
1881 features.require("japanese");
1883 if ((!encodings.empty() || package == Encoding::inputenc)
1884 && !features.isRequired("japanese")) {
1885 os << "\\usepackage[";
1886 set<string>::const_iterator it = encodings.begin();
1887 set<string>::const_iterator const end = encodings.end();
1889 os << from_ascii(*it);
1892 for (; it != end; ++it)
1893 os << ',' << from_ascii(*it);
1894 if (package == Encoding::inputenc) {
1895 if (!encodings.empty())
1897 os << from_ascii(doc_encoding);
1899 os << "]{inputenc}\n";
1902 if (package == Encoding::CJK || features.mustProvide("CJK")) {
1903 if (language->encoding()->name() == "utf8-cjk"
1904 && LaTeXFeatures::isAvailable("CJKutf8"))
1905 os << "\\usepackage{CJKutf8}\n";
1907 os << "\\usepackage{CJK}\n";
1910 } else if (inputenc != "default") {
1911 switch (encoding().package()) {
1912 case Encoding::none:
1913 case Encoding::japanese:
1915 case Encoding::inputenc:
1916 // do not load inputenc if japanese is used
1917 if (features.isRequired("japanese"))
1919 os << "\\usepackage[" << from_ascii(inputenc)
1924 if (encoding().name() == "utf8-cjk"
1925 && LaTeXFeatures::isAvailable("CJKutf8"))
1926 os << "\\usepackage{CJKutf8}\n";
1928 os << "\\usepackage{CJK}\n";
1934 // The encoding "armscii8" (for Armenian) is only available when
1935 // the package "armtex" is loaded.
1936 if (language->encoding()->latexName() == "armscii8"
1937 || inputenc == "armscii8") {
1938 os << "\\usepackage{armtex}\n";
1944 string const BufferParams::loadFonts(string const & rm,
1945 string const & sf, string const & tt,
1946 bool const & sc, bool const & osf,
1947 int const & sfscale, int const & ttscale) const
1949 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1950 several packages have been replaced by others, that might not
1951 be installed on every system. We have to take care for that
1952 (see psnfss.pdf). We try to support all psnfss fonts as well
1953 as the fonts that have become de facto standard in the LaTeX
1954 world (e.g. Latin Modern). We do not support obsolete fonts
1955 (like PSLatex). In general, it should be possible to mix any
1956 rm font with any sf or tt font, respectively. (JSpitzm)
1958 -- separate math fonts.
1961 if (rm == "default" && sf == "default" && tt == "default")
1968 // Computer Modern (must be explicitely selectable -- there might be classes
1969 // that define a different default font!
1971 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1972 // osf for Computer Modern needs eco.sty
1974 os << "\\usepackage{eco}\n";
1976 // Latin Modern Roman
1977 else if (rm == "lmodern")
1978 os << "\\usepackage{lmodern}\n";
1980 else if (rm == "ae") {
1981 // not needed when using OT1 font encoding.
1982 if (lyxrc.fontenc != "default")
1983 os << "\\usepackage{ae,aecompl}\n";
1986 else if (rm == "times") {
1987 // try to load the best available package
1988 if (LaTeXFeatures::isAvailable("mathptmx"))
1989 os << "\\usepackage{mathptmx}\n";
1990 else if (LaTeXFeatures::isAvailable("mathptm"))
1991 os << "\\usepackage{mathptm}\n";
1993 os << "\\usepackage{times}\n";
1996 else if (rm == "palatino") {
1997 // try to load the best available package
1998 if (LaTeXFeatures::isAvailable("mathpazo")) {
1999 os << "\\usepackage";
2005 // "osf" includes "sc"!
2009 os << "{mathpazo}\n";
2011 else if (LaTeXFeatures::isAvailable("mathpple"))
2012 os << "\\usepackage{mathpple}\n";
2014 os << "\\usepackage{palatino}\n";
2017 else if (rm == "utopia") {
2018 // fourier supersedes utopia.sty, but does
2019 // not work with OT1 encoding.
2020 if (LaTeXFeatures::isAvailable("fourier")
2021 && lyxrc.fontenc != "default") {
2022 os << "\\usepackage";
2033 os << "{fourier}\n";
2036 os << "\\usepackage{utopia}\n";
2038 // Bera (complete fontset)
2039 else if (rm == "bera" && sf == "default" && tt == "default")
2040 os << "\\usepackage{bera}\n";
2042 else if (rm != "default")
2043 os << "\\usepackage" << "{" << rm << "}\n";
2046 // Helvetica, Bera Sans
2047 if (sf == "helvet" || sf == "berasans") {
2049 os << "\\usepackage[scaled=" << float(sfscale) / 100
2050 << "]{" << sf << "}\n";
2052 os << "\\usepackage{" << sf << "}\n";
2055 else if (sf == "avant")
2056 os << "\\usepackage{" << sf << "}\n";
2057 // Computer Modern, Latin Modern, CM Bright
2058 else if (sf != "default")
2059 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2061 // monospaced/typewriter
2062 // Courier, LuxiMono
2063 if (tt == "luximono" || tt == "beramono") {
2065 os << "\\usepackage[scaled=" << float(ttscale) / 100
2066 << "]{" << tt << "}\n";
2068 os << "\\usepackage{" << tt << "}\n";
2071 else if (tt == "courier" )
2072 os << "\\usepackage{" << tt << "}\n";
2073 // Computer Modern, Latin Modern, CM Bright
2074 else if (tt != "default")
2075 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2081 Encoding const & BufferParams::encoding() const
2083 if (inputenc == "auto" || inputenc == "default")
2084 return *language->encoding();
2085 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2088 LYXERR0("Unknown inputenc value `" << inputenc
2089 << "'. Using `auto' instead.");
2090 return *language->encoding();
2094 CiteEngine BufferParams::citeEngine() const
2096 // FIXME the class should provide the numerical/
2097 // authoryear choice
2098 if (documentClass().provides("natbib")
2099 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2100 return ENGINE_NATBIB_AUTHORYEAR;
2101 return cite_engine_;
2105 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2107 cite_engine_ = cite_engine;