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"
28 #include "LaTeXFeatures.h"
29 #include "ModuleList.h"
33 #include "OutputParams.h"
37 #include "PDFOptions.h"
39 #include "frontends/alert.h"
41 #include "insets/InsetListingsParams.h"
43 #include "support/convert.h"
44 #include "support/debug.h"
45 #include "support/docstream.h"
46 #include "support/FileName.h"
47 #include "support/filetools.h"
48 #include "support/gettext.h"
49 #include "support/Messages.h"
50 #include "support/Translator.h"
51 #include "support/lstrings.h"
57 using namespace lyx::support;
60 static char const * const string_paragraph_separation[] = {
65 static char const * const string_quotes_language[] = {
66 "english", "swedish", "german", "polish", "french", "danish", ""
70 static char const * const string_papersize[] = {
71 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
72 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
76 static char const * const string_orientation[] = {
77 "portrait", "landscape", ""
81 static char const * const string_footnotekinds[] = {
82 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
86 static char const * const tex_graphics[] = {
87 "default", "dvips", "dvitops", "emtex",
88 "ln", "oztex", "textures", "none", ""
97 // Paragraph separation
98 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
101 ParSepTranslator const init_parseptranslator()
103 ParSepTranslator translator
104 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
105 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
110 ParSepTranslator const & parseptranslator()
112 static ParSepTranslator translator = init_parseptranslator();
118 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
121 QuotesLangTranslator const init_quoteslangtranslator()
123 QuotesLangTranslator translator
124 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
125 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
126 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
127 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
128 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
129 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
134 QuotesLangTranslator const & quoteslangtranslator()
136 static QuotesLangTranslator translator = init_quoteslangtranslator();
142 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
145 static PaperSizeTranslator initPaperSizeTranslator()
147 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
148 translator.addPair(string_papersize[1], PAPER_CUSTOM);
149 translator.addPair(string_papersize[2], PAPER_USLETTER);
150 translator.addPair(string_papersize[3], PAPER_USLEGAL);
151 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
152 translator.addPair(string_papersize[5], PAPER_A3);
153 translator.addPair(string_papersize[6], PAPER_A4);
154 translator.addPair(string_papersize[7], PAPER_A5);
155 translator.addPair(string_papersize[8], PAPER_B3);
156 translator.addPair(string_papersize[9], PAPER_B4);
157 translator.addPair(string_papersize[10], PAPER_B5);
162 PaperSizeTranslator const & papersizetranslator()
164 static PaperSizeTranslator translator = initPaperSizeTranslator();
170 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
173 PaperOrientationTranslator const init_paperorientationtranslator()
175 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
176 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
181 PaperOrientationTranslator const & paperorientationtranslator()
183 static PaperOrientationTranslator translator = init_paperorientationtranslator();
189 typedef Translator<int, PageSides> SidesTranslator;
192 SidesTranslator const init_sidestranslator()
194 SidesTranslator translator(1, OneSide);
195 translator.addPair(2, TwoSides);
200 SidesTranslator const & sidestranslator()
202 static SidesTranslator translator = init_sidestranslator();
208 typedef Translator<int, BufferParams::Package> PackageTranslator;
211 PackageTranslator const init_packagetranslator()
213 PackageTranslator translator(0, BufferParams::package_off);
214 translator.addPair(1, BufferParams::package_auto);
215 translator.addPair(2, BufferParams::package_on);
220 PackageTranslator const & packagetranslator()
222 static PackageTranslator translator = init_packagetranslator();
228 typedef Translator<string, CiteEngine> CiteEngineTranslator;
231 CiteEngineTranslator const init_citeenginetranslator()
233 CiteEngineTranslator translator("basic", ENGINE_BASIC);
234 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
235 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
236 translator.addPair("jurabib", ENGINE_JURABIB);
241 CiteEngineTranslator const & citeenginetranslator()
243 static CiteEngineTranslator translator = init_citeenginetranslator();
249 typedef Translator<string, Spacing::Space> SpaceTranslator;
252 SpaceTranslator const init_spacetranslator()
254 SpaceTranslator translator("default", Spacing::Default);
255 translator.addPair("single", Spacing::Single);
256 translator.addPair("onehalf", Spacing::Onehalf);
257 translator.addPair("double", Spacing::Double);
258 translator.addPair("other", Spacing::Other);
263 SpaceTranslator const & spacetranslator()
265 static SpaceTranslator translator = init_spacetranslator();
273 class BufferParams::Impl
278 AuthorList authorlist;
279 BranchList branchlist;
280 Bullet temp_bullets[4];
281 Bullet user_defined_bullets[4];
283 /** This is the amount of space used for paragraph_separation "skip",
284 * and for detached paragraphs in "indented" documents.
287 PDFOptions pdfoptions;
288 LayoutFileIndex baseClass_;
292 BufferParams::Impl::Impl()
293 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
295 // set initial author
297 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
302 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
306 return new BufferParams::Impl(*ptr);
310 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
316 BufferParams::BufferParams()
319 setBaseClass(defaultBaseclass());
321 paragraph_separation = ParagraphIndentSeparation;
322 quotes_language = InsetQuotes::EnglishQuotes;
323 fontsize = "default";
326 papersize = PAPER_DEFAULT;
327 orientation = ORIENTATION_PORTRAIT;
328 use_geometry = false;
329 use_amsmath = package_auto;
330 use_esint = package_auto;
331 cite_engine_ = ENGINE_BASIC;
332 use_bibtopic = false;
333 trackChanges = false;
334 outputChanges = false;
337 language = default_language;
338 fontsRoman = "default";
339 fontsSans = "default";
340 fontsTypewriter = "default";
341 fontsDefaultFamily = "default";
344 fontsSansScale = 100;
345 fontsTypewriterScale = 100;
347 graphicsDriver = "default";
350 listings_params = string();
351 pagestyle = "default";
353 for (int iter = 0; iter < 4; ++iter) {
354 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
355 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
360 docstring BufferParams::B_(string const & l10n) const
362 LASSERT(language, /**/);
363 return getMessages(language->code()).get(l10n);
367 AuthorList & BufferParams::authors()
369 return pimpl_->authorlist;
373 AuthorList const & BufferParams::authors() const
375 return pimpl_->authorlist;
379 BranchList & BufferParams::branchlist()
381 return pimpl_->branchlist;
385 BranchList const & BufferParams::branchlist() const
387 return pimpl_->branchlist;
391 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
393 LASSERT(index < 4, /**/);
394 return pimpl_->temp_bullets[index];
398 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
400 LASSERT(index < 4, /**/);
401 return pimpl_->temp_bullets[index];
405 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
407 LASSERT(index < 4, /**/);
408 return pimpl_->user_defined_bullets[index];
412 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
414 LASSERT(index < 4, /**/);
415 return pimpl_->user_defined_bullets[index];
419 Spacing & BufferParams::spacing()
421 return pimpl_->spacing;
425 Spacing const & BufferParams::spacing() const
427 return pimpl_->spacing;
431 PDFOptions & BufferParams::pdfoptions()
433 return pimpl_->pdfoptions;
437 PDFOptions const & BufferParams::pdfoptions() const
439 return pimpl_->pdfoptions;
443 VSpace const & BufferParams::getDefSkip() const
445 return pimpl_->defskip;
449 void BufferParams::setDefSkip(VSpace const & vs)
451 pimpl_->defskip = vs;
455 string BufferParams::readToken(Lexer & lex, string const & token,
456 FileName const & filepath)
458 if (token == "\\textclass") {
460 string const classname = lex.getString();
461 // if there exists a local layout file, ignore the system one
462 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
464 LayoutFileList & bcl = LayoutFileList::get();
465 if (tcp.empty() && !filepath.empty())
466 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
470 setBaseClass(classname);
471 // We assume that a tex class exists for local or unknown layouts so this warning
472 // will only be given for system layouts.
473 if (!baseClass()->isTeXClassAvailable()) {
474 docstring const msg =
475 bformat(_("The layout file requested by this document,\n"
477 "is not usable. This is probably because a LaTeX\n"
478 "class or style file required by it is not\n"
479 "available. See the Customization documentation\n"
480 "for more information.\n"), from_utf8(classname));
481 frontend::Alert::warning(_("Document class not available"),
482 msg + _("LyX will not be able to produce output."));
484 } else if (token == "\\begin_preamble") {
486 } else if (token == "\\begin_local_layout") {
487 readLocalLayout(lex);
488 } else if (token == "\\begin_modules") {
490 } else if (token == "\\begin_removed_modules") {
491 readRemovedModules(lex);
492 } else if (token == "\\options") {
494 options = lex.getString();
495 } else if (token == "\\master") {
497 master = lex.getString();
498 } else if (token == "\\language") {
500 } else if (token == "\\inputencoding") {
502 } else if (token == "\\graphics") {
503 readGraphicsDriver(lex);
504 } else if (token == "\\font_roman") {
506 } else if (token == "\\font_sans") {
508 } else if (token == "\\font_typewriter") {
509 lex >> fontsTypewriter;
510 } else if (token == "\\font_default_family") {
511 lex >> fontsDefaultFamily;
512 } else if (token == "\\font_sc") {
514 } else if (token == "\\font_osf") {
516 } else if (token == "\\font_sf_scale") {
517 lex >> fontsSansScale;
518 } else if (token == "\\font_tt_scale") {
519 lex >> fontsTypewriterScale;
520 } else if (token == "\\font_cjk") {
522 } else if (token == "\\paragraph_separation") {
525 paragraph_separation = parseptranslator().find(parsep);
526 } else if (token == "\\defskip") {
528 string defskip = lex.getString();
529 if (defskip == "defskip")
532 pimpl_->defskip = VSpace(defskip);
533 } else if (token == "\\quotes_language") {
536 quotes_language = quoteslangtranslator().find(quotes_lang);
537 } else if (token == "\\papersize") {
540 papersize = papersizetranslator().find(ppsize);
541 } else if (token == "\\use_geometry") {
543 } else if (token == "\\use_amsmath") {
546 use_amsmath = packagetranslator().find(use_ams);
547 } else if (token == "\\use_esint") {
550 use_esint = packagetranslator().find(useesint);
551 } else if (token == "\\cite_engine") {
554 cite_engine_ = citeenginetranslator().find(engine);
555 } else if (token == "\\use_bibtopic") {
557 } else if (token == "\\tracking_changes") {
559 } else if (token == "\\output_changes") {
560 lex >> outputChanges;
561 } else if (token == "\\branch") {
563 docstring branch = lex.getDocString();
564 branchlist().add(branch);
567 string const tok = lex.getString();
568 if (tok == "\\end_branch")
570 Branch * branch_ptr = branchlist().find(branch);
571 if (tok == "\\selected") {
574 branch_ptr->setSelected(lex.getInteger());
576 // not yet operational
577 if (tok == "\\color") {
579 string color = lex.getString();
581 branch_ptr->setColor(color);
582 // Update also the Color table:
584 color = lcolor.getX11Name(Color_background);
586 lcolor.setColor(to_utf8(branch), color);
590 } else if (token == "\\author") {
592 istringstream ss(lex.getString());
595 author_map.push_back(pimpl_->authorlist.record(a));
596 } else if (token == "\\paperorientation") {
599 orientation = paperorientationtranslator().find(orient);
600 } else if (token == "\\paperwidth") {
602 } else if (token == "\\paperheight") {
604 } else if (token == "\\leftmargin") {
606 } else if (token == "\\topmargin") {
608 } else if (token == "\\rightmargin") {
610 } else if (token == "\\bottommargin") {
612 } else if (token == "\\headheight") {
614 } else if (token == "\\headsep") {
616 } else if (token == "\\footskip") {
618 } else if (token == "\\columnsep") {
620 } else if (token == "\\paperfontsize") {
622 } else if (token == "\\papercolumns") {
624 } else if (token == "\\listings_params") {
627 listings_params = InsetListingsParams(par).params();
628 } else if (token == "\\papersides") {
631 sides = sidestranslator().find(psides);
632 } else if (token == "\\paperpagestyle") {
634 } else if (token == "\\bullet") {
636 } else if (token == "\\bulletLaTeX") {
637 readBulletsLaTeX(lex);
638 } else if (token == "\\secnumdepth") {
640 } else if (token == "\\tocdepth") {
642 } else if (token == "\\spacing") {
646 if (nspacing == "other") {
649 spacing().set(spacetranslator().find(nspacing), tmp_val);
650 } else if (token == "\\float_placement") {
651 lex >> float_placement;
653 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
654 string toktmp = pdfoptions().readToken(lex, token);
655 if (!toktmp.empty()) {
656 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
661 lyxerr << "BufferParams::readToken(): Unknown token: " <<
670 void BufferParams::writeFile(ostream & os) const
672 // The top of the file is written by the buffer.
673 // Prints out the buffer info into the .lyx file given by file
676 os << "\\textclass " << baseClass()->name() << '\n';
679 if (!preamble.empty()) {
680 // remove '\n' from the end of preamble
681 string const tmppreamble = rtrim(preamble, "\n");
682 os << "\\begin_preamble\n"
684 << "\n\\end_preamble\n";
688 if (!options.empty()) {
689 os << "\\options " << options << '\n';
692 // the master document
693 if (!master.empty()) {
694 os << "\\master " << master << '\n';
698 if (!removedModules_.empty()) {
699 os << "\\begin_removed_modules" << '\n';
700 set<string>::const_iterator it = removedModules_.begin();
701 set<string>::const_iterator en = removedModules_.end();
702 for (; it != en; it++)
704 os << "\\end_removed_modules" << '\n';
708 if (!layoutModules_.empty()) {
709 os << "\\begin_modules" << '\n';
710 LayoutModuleList::const_iterator it = layoutModules_.begin();
711 LayoutModuleList::const_iterator en = layoutModules_.end();
712 for (; it != en; it++)
714 os << "\\end_modules" << '\n';
717 // local layout information
718 if (!local_layout.empty()) {
719 // remove '\n' from the end
720 string const tmplocal = rtrim(local_layout, "\n");
721 os << "\\begin_local_layout\n"
723 << "\n\\end_local_layout\n";
726 // then the text parameters
727 if (language != ignore_language)
728 os << "\\language " << language->lang() << '\n';
729 os << "\\inputencoding " << inputenc
730 << "\n\\font_roman " << fontsRoman
731 << "\n\\font_sans " << fontsSans
732 << "\n\\font_typewriter " << fontsTypewriter
733 << "\n\\font_default_family " << fontsDefaultFamily
734 << "\n\\font_sc " << convert<string>(fontsSC)
735 << "\n\\font_osf " << convert<string>(fontsOSF)
736 << "\n\\font_sf_scale " << fontsSansScale
737 << "\n\\font_tt_scale " << fontsTypewriterScale
739 if (!fontsCJK.empty()) {
740 os << "\\font_cjk " << fontsCJK << '\n';
742 os << "\n\\graphics " << graphicsDriver << '\n';
744 if (!float_placement.empty()) {
745 os << "\\float_placement " << float_placement << '\n';
747 os << "\\paperfontsize " << fontsize << '\n';
749 spacing().writeFile(os);
750 pdfoptions().writeFile(os);
752 os << "\\papersize " << string_papersize[papersize]
753 << "\n\\use_geometry " << convert<string>(use_geometry)
754 << "\n\\use_amsmath " << use_amsmath
755 << "\n\\use_esint " << use_esint
756 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
757 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
758 << "\n\\paperorientation " << string_orientation[orientation]
761 BranchList::const_iterator it = branchlist().begin();
762 BranchList::const_iterator end = branchlist().end();
763 for (; it != end; ++it) {
764 os << "\\branch " << to_utf8(it->branch())
765 << "\n\\selected " << it->isSelected()
766 << "\n\\color " << lyx::X11hexname(it->color())
771 if (!paperwidth.empty())
772 os << "\\paperwidth "
773 << VSpace(paperwidth).asLyXCommand() << '\n';
774 if (!paperheight.empty())
775 os << "\\paperheight "
776 << VSpace(paperheight).asLyXCommand() << '\n';
777 if (!leftmargin.empty())
778 os << "\\leftmargin "
779 << VSpace(leftmargin).asLyXCommand() << '\n';
780 if (!topmargin.empty())
782 << VSpace(topmargin).asLyXCommand() << '\n';
783 if (!rightmargin.empty())
784 os << "\\rightmargin "
785 << VSpace(rightmargin).asLyXCommand() << '\n';
786 if (!bottommargin.empty())
787 os << "\\bottommargin "
788 << VSpace(bottommargin).asLyXCommand() << '\n';
789 if (!headheight.empty())
790 os << "\\headheight "
791 << VSpace(headheight).asLyXCommand() << '\n';
792 if (!headsep.empty())
794 << VSpace(headsep).asLyXCommand() << '\n';
795 if (!footskip.empty())
797 << VSpace(footskip).asLyXCommand() << '\n';
798 if (!columnsep.empty())
800 << VSpace(columnsep).asLyXCommand() << '\n';
801 os << "\\secnumdepth " << secnumdepth
802 << "\n\\tocdepth " << tocdepth
803 << "\n\\paragraph_separation "
804 << string_paragraph_separation[paragraph_separation]
805 << "\n\\defskip " << getDefSkip().asLyXCommand()
806 << "\n\\quotes_language "
807 << string_quotes_language[quotes_language]
808 << "\n\\papercolumns " << columns
809 << "\n\\papersides " << sides
810 << "\n\\paperpagestyle " << pagestyle << '\n';
811 if (!listings_params.empty())
812 os << "\\listings_params \"" <<
813 InsetListingsParams(listings_params).encodedString() << "\"\n";
814 for (int i = 0; i < 4; ++i) {
815 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
816 if (user_defined_bullet(i).getFont() != -1) {
817 os << "\\bullet " << i << " "
818 << user_defined_bullet(i).getFont() << " "
819 << user_defined_bullet(i).getCharacter() << " "
820 << user_defined_bullet(i).getSize() << "\n";
824 os << "\\bulletLaTeX " << i << " \""
825 << lyx::to_ascii(user_defined_bullet(i).getText())
831 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
832 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
834 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
835 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
836 for (; a_it != a_end; ++a_it) {
837 if (a_it->second.used())
838 os << "\\author " << a_it->second << "\n";
840 os << "\\author " << Author() << "\n";
845 void BufferParams::validate(LaTeXFeatures & features) const
847 features.require(documentClass().requires());
850 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
851 bool xcolorsoul = LaTeXFeatures::isAvailable("soul") &&
852 LaTeXFeatures::isAvailable("xcolor");
854 switch (features.runparams().flavor) {
855 case OutputParams::LATEX:
857 features.require("ct-dvipost");
858 features.require("dvipost");
859 } else if (xcolorsoul) {
860 features.require("ct-xcolor-soul");
861 features.require("soul");
862 features.require("xcolor");
864 features.require("ct-none");
867 case OutputParams::PDFLATEX:
869 features.require("ct-xcolor-soul");
870 features.require("soul");
871 features.require("xcolor");
872 // improves color handling in PDF output
873 features.require("pdfcolmk");
875 features.require("ct-none");
883 // Floats with 'Here definitely' as default setting.
884 if (float_placement.find('H') != string::npos)
885 features.require("float");
887 // AMS Style is at document level
888 if (use_amsmath == package_on
889 || documentClass().provides("amsmath"))
890 features.require("amsmath");
891 if (use_esint == package_on)
892 features.require("esint");
894 // Document-level line spacing
895 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
896 features.require("setspace");
898 // the bullet shapes are buffer level not paragraph level
899 // so they are tested here
900 for (int i = 0; i < 4; ++i) {
901 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
903 int const font = user_defined_bullet(i).getFont();
905 int const c = user_defined_bullet(i).getCharacter();
911 features.require("latexsym");
913 } else if (font == 1) {
914 features.require("amssymb");
915 } else if (font >= 2 && font <= 5) {
916 features.require("pifont");
920 if (pdfoptions().use_hyperref) {
921 features.require("hyperref");
922 // due to interferences with babel and hyperref, the color package has to
923 // be loaded after hyperref when hyperref is used with the colorlinks
924 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
925 if (pdfoptions().colorlinks)
926 features.require("color");
929 if (language->lang() == "vietnamese")
930 features.require("vietnamese");
931 else if (language->lang() == "japanese")
932 features.require("japanese");
936 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
937 TexRow & texrow) const
939 os << "\\documentclass";
941 DocumentClass const & tclass = documentClass();
943 ostringstream clsoptions; // the document class options.
945 if (tokenPos(tclass.opt_fontsize(),
946 '|', fontsize) >= 0) {
947 // only write if existing in list (and not default)
948 clsoptions << fontsize << "pt,";
951 // custom, A3, B3 and B4 paper sizes need geometry
952 bool nonstandard_papersize = papersize == PAPER_B3
953 || papersize == PAPER_B4
954 || papersize == PAPER_A3
955 || papersize == PAPER_CUSTOM;
960 clsoptions << "a4paper,";
963 clsoptions << "letterpaper,";
966 clsoptions << "a5paper,";
969 clsoptions << "b5paper,";
971 case PAPER_USEXECUTIVE:
972 clsoptions << "executivepaper,";
975 clsoptions << "legalpaper,";
987 if (sides != tclass.sides()) {
990 clsoptions << "oneside,";
993 clsoptions << "twoside,";
999 if (columns != tclass.columns()) {
1001 clsoptions << "twocolumn,";
1003 clsoptions << "onecolumn,";
1007 && orientation == ORIENTATION_LANDSCAPE)
1008 clsoptions << "landscape,";
1010 // language should be a parameter to \documentclass
1011 if (language->babel() == "hebrew"
1012 && default_language->babel() != "hebrew")
1013 // This seems necessary
1014 features.useLanguage(default_language);
1016 ostringstream language_options;
1017 bool const use_babel = features.useBabel();
1019 language_options << features.getLanguages();
1020 if (!language->babel().empty()) {
1021 if (!language_options.str().empty())
1022 language_options << ',';
1023 language_options << language->babel();
1025 // if Vietnamese is used, babel must directly be loaded
1026 // with language options, not in the class options, see
1027 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1028 size_t viet = language_options.str().find("vietnam");
1029 // viet = string::npos when not found
1030 // if Japanese is used, babel must directly be loaded
1031 // with language options, not in the class options, see
1032 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1033 size_t japan = language_options.str().find("japanese");
1034 // japan = string::npos when not found
1035 if (lyxrc.language_global_options
1036 && !language_options.str().empty()
1037 && viet == string::npos && japan == string::npos)
1038 clsoptions << language_options.str() << ',';
1041 // the user-defined options
1042 if (!options.empty()) {
1043 clsoptions << options << ',';
1046 string strOptions(clsoptions.str());
1047 if (!strOptions.empty()) {
1048 strOptions = rtrim(strOptions, ",");
1050 os << '[' << from_utf8(strOptions) << ']';
1053 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1055 // end of \documentclass defs
1057 // font selection must be done before loading fontenc.sty
1058 string const fonts =
1059 loadFonts(fontsRoman, fontsSans,
1060 fontsTypewriter, fontsSC, fontsOSF,
1061 fontsSansScale, fontsTypewriterScale);
1062 if (!fonts.empty()) {
1063 os << from_ascii(fonts);
1066 if (fontsDefaultFamily != "default")
1067 os << "\\renewcommand{\\familydefault}{\\"
1068 << from_ascii(fontsDefaultFamily) << "}\n";
1070 // set font encoding
1071 // this one is not per buffer
1072 // for arabic_arabi and farsi we also need to load the LAE and
1074 if (lyxrc.fontenc != "default" && language->lang() != "japanese") {
1075 if (language->lang() == "arabic_arabi"
1076 || language->lang() == "farsi") {
1077 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1078 << ",LFE,LAE]{fontenc}\n";
1081 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1087 // handle inputenc etc.
1088 writeEncodingPreamble(os, features, texrow);
1090 if (!listings_params.empty() || features.isRequired("listings")) {
1091 os << "\\usepackage{listings}\n";
1094 if (!listings_params.empty()) {
1096 // do not test validity because listings_params is
1097 // supposed to be valid
1099 InsetListingsParams(listings_params).separatedParams(true);
1100 // we can't support all packages, but we should load the color package
1101 if (par.find("\\color", 0) != string::npos)
1102 features.require("color");
1103 os << from_utf8(par);
1104 // count the number of newlines
1105 for (size_t i = 0; i < par.size(); ++i)
1111 if (use_geometry || nonstandard_papersize) {
1112 os << "\\usepackage{geometry}\n";
1114 os << "\\geometry{verbose";
1115 if (orientation == ORIENTATION_LANDSCAPE)
1117 switch (papersize) {
1119 if (!paperwidth.empty())
1120 os << ",paperwidth="
1121 << from_ascii(paperwidth);
1122 if (!paperheight.empty())
1123 os << ",paperheight="
1124 << from_ascii(paperheight);
1126 case PAPER_USLETTER:
1127 os << ",letterpaper";
1130 os << ",legalpaper";
1132 case PAPER_USEXECUTIVE:
1133 os << ",executivepaper";
1154 // default papersize ie PAPER_DEFAULT
1155 switch (lyxrc.default_papersize) {
1156 case PAPER_DEFAULT: // keep compiler happy
1157 case PAPER_USLETTER:
1158 os << ",letterpaper";
1161 os << ",legalpaper";
1163 case PAPER_USEXECUTIVE:
1164 os << ",executivepaper";
1184 if (!topmargin.empty())
1185 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1186 if (!bottommargin.empty())
1187 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1188 if (!leftmargin.empty())
1189 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1190 if (!rightmargin.empty())
1191 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1192 if (!headheight.empty())
1193 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1194 if (!headsep.empty())
1195 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1196 if (!footskip.empty())
1197 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1198 if (!columnsep.empty())
1199 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1202 } else if (orientation == ORIENTATION_LANDSCAPE) {
1203 features.require("papersize");
1206 if (tokenPos(tclass.opt_pagestyle(),
1207 '|', pagestyle) >= 0) {
1208 if (pagestyle == "fancy") {
1209 os << "\\usepackage{fancyhdr}\n";
1212 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1216 // Only if class has a ToC hierarchy
1217 if (tclass.hasTocLevels()) {
1218 if (secnumdepth != tclass.secnumdepth()) {
1219 os << "\\setcounter{secnumdepth}{"
1224 if (tocdepth != tclass.tocdepth()) {
1225 os << "\\setcounter{tocdepth}{"
1232 if (paragraph_separation) {
1233 switch (getDefSkip().kind()) {
1234 case VSpace::SMALLSKIP:
1235 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1237 case VSpace::MEDSKIP:
1238 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1240 case VSpace::BIGSKIP:
1241 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1243 case VSpace::LENGTH:
1244 os << "\\setlength{\\parskip}{"
1245 << from_utf8(getDefSkip().length().asLatexString())
1248 default: // should never happen // Then delete it.
1249 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1254 os << "\\setlength{\\parindent}{0pt}\n";
1258 // Now insert the LyX specific LaTeX commands...
1259 docstring lyxpreamble;
1261 // due to interferences with babel and hyperref, the color package has to
1262 // be loaded (when it is not already loaded) before babel when hyperref
1263 // is used with the colorlinks option, see
1264 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1265 // we decided therefore to load color always before babel, see
1266 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1267 lyxpreamble += from_ascii(features.getColorOptions());
1269 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1271 && (features.isRequired("jurabib")
1272 || features.isRequired("hyperref")
1273 || features.isRequired("vietnamese")
1274 || features.isRequired("japanese") ) ) {
1276 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1277 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1280 // The optional packages;
1281 lyxpreamble += from_ascii(features.getPackages());
1284 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1287 // * Hyperref manual: "Make sure it comes last of your loaded
1288 // packages, to give it a fighting chance of not being over-written,
1289 // since its job is to redefine many LATEX commands."
1290 // * Email from Heiko Oberdiek: "It is usually better to load babel
1291 // before hyperref. Then hyperref has a chance to detect babel.
1292 // * Has to be loaded before the "LyX specific LaTeX commands" to
1293 // avoid errors with algorithm floats.
1294 // use hyperref explicitely when it is required
1295 if (features.isRequired("hyperref")) {
1296 odocstringstream oss;
1297 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1298 lyxpreamble += oss.str();
1301 // Will be surrounded by \makeatletter and \makeatother when needed
1302 docstring atlyxpreamble;
1304 // Some macros LyX will need
1305 docstring tmppreamble(from_ascii(features.getMacros()));
1307 if (!tmppreamble.empty())
1308 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1309 "LyX specific LaTeX commands.\n"
1310 + tmppreamble + '\n';
1312 // the text class specific preamble
1313 tmppreamble = features.getTClassPreamble();
1314 if (!tmppreamble.empty())
1315 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1316 "Textclass specific LaTeX commands.\n"
1317 + tmppreamble + '\n';
1319 /* the user-defined preamble */
1320 if (!preamble.empty())
1322 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1323 "User specified LaTeX commands.\n"
1324 + from_utf8(preamble) + '\n';
1326 // subfig loads internally the LaTeX package "caption". As
1327 // caption is a very popular package, users will load it in
1328 // the preamble. Therefore we must load subfig behind the
1329 // user-defined preamble and check if the caption package was
1330 // loaded or not. For the case that caption is loaded before
1331 // subfig, there is the subfig option "caption=false". This
1332 // option also works when a koma-script class is used and
1333 // koma's own caption commands are used instead of caption. We
1334 // use \PassOptionsToPackage here because the user could have
1335 // already loaded subfig in the preamble.
1336 if (features.isRequired("subfig")) {
1337 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1338 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1339 "\\usepackage{subfig}\n";
1342 // Itemize bullet settings need to be last in case the user
1343 // defines their own bullets that use a package included
1344 // in the user-defined preamble -- ARRae
1345 // Actually it has to be done much later than that
1346 // since some packages like frenchb make modifications
1347 // at \begin{document} time -- JMarc
1348 docstring bullets_def;
1349 for (int i = 0; i < 4; ++i) {
1350 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1351 if (bullets_def.empty())
1352 bullets_def += "\\AtBeginDocument{\n";
1353 bullets_def += " \\def\\labelitemi";
1355 // `i' is one less than the item to modify
1362 bullets_def += "ii";
1368 bullets_def += '{' +
1369 user_defined_bullet(i).getText()
1374 if (!bullets_def.empty())
1375 atlyxpreamble += bullets_def + "}\n\n";
1377 if (atlyxpreamble.find(from_ascii("@")) != docstring::npos)
1378 lyxpreamble += "\n\\makeatletter\n"
1379 + atlyxpreamble + "\\makeatother\n\n";
1381 lyxpreamble += '\n' + atlyxpreamble;
1383 // We try to load babel late, in case it interferes with other packages.
1384 // Jurabib and Hyperref have to be called after babel, though.
1385 if (use_babel && !features.isRequired("jurabib")
1386 && !features.isRequired("hyperref")
1387 && !features.isRequired("vietnamese")
1388 && !features.isRequired("japanese")) {
1390 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1391 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1395 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1396 for (int j = 0; j != nlines; ++j) {
1405 void BufferParams::useClassDefaults()
1407 DocumentClass const & tclass = documentClass();
1409 sides = tclass.sides();
1410 columns = tclass.columns();
1411 pagestyle = tclass.pagestyle();
1412 options = tclass.options();
1413 // Only if class has a ToC hierarchy
1414 if (tclass.hasTocLevels()) {
1415 secnumdepth = tclass.secnumdepth();
1416 tocdepth = tclass.tocdepth();
1421 bool BufferParams::hasClassDefaults() const
1423 DocumentClass const & tclass = documentClass();
1425 return sides == tclass.sides()
1426 && columns == tclass.columns()
1427 && pagestyle == tclass.pagestyle()
1428 && options == tclass.options()
1429 && secnumdepth == tclass.secnumdepth()
1430 && tocdepth == tclass.tocdepth();
1434 DocumentClass const & BufferParams::documentClass() const
1440 DocumentClass const * BufferParams::documentClassPtr() const {
1445 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1446 // evil, but this function is evil
1447 doc_class_ = const_cast<DocumentClass *>(tc);
1451 bool BufferParams::setBaseClass(string const & classname)
1453 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1454 LayoutFileList & bcl = LayoutFileList::get();
1455 if (!bcl.haveClass(classname)) {
1457 bformat(_("The document class %1$s could not be found. "
1458 "A default textclass with default layouts will be used. "
1459 "LyX might not be able to produce output unless a correct "
1460 "textclass is selected from the document settings dialog."),
1461 from_utf8(classname));
1462 frontend::Alert::error(_("Document class not found"), s);
1463 bcl.addEmptyClass(classname);
1466 bool const success = bcl[classname].load();
1469 bformat(_("The document class %1$s could not be loaded."),
1470 from_utf8(classname));
1471 frontend::Alert::error(_("Could not load class"), s);
1475 pimpl_->baseClass_ = classname;
1477 // add any required modules not already in use
1478 set<string> const & mods = baseClass()->defaultModules();
1479 set<string>::const_iterator mit = mods.begin();
1480 set<string>::const_iterator men = mods.end();
1481 for (; mit != men; mit++) {
1482 string const & modName = *mit;
1483 // see if we're already in use
1484 if (find(layoutModules_.begin(), layoutModules_.end(), modName) !=
1485 layoutModules_.end()) {
1486 LYXERR(Debug::TCLASS, "Default module `" << modName <<
1487 "' not added because already used.");
1490 // make sure the user hasn't removed it
1491 if (find(removedModules_.begin(), removedModules_.end(), modName) !=
1492 removedModules_.end()) {
1493 LYXERR(Debug::TCLASS, "Default module `" << modName <<
1494 "' not added because removed by user.");
1497 // Now we want to check the list of selected modules to see if any of them
1498 // exclude this one.
1499 bool foundit = false;
1500 // so iterate over the selected modules...
1501 LayoutModuleList::const_iterator lit = layoutModules_.begin();
1502 LayoutModuleList::const_iterator len = layoutModules_.end();
1503 for (; lit != len; lit++) {
1504 LyXModule * lm = moduleList[*lit];
1507 vector<string> const & exc = lm->getExcludedModules();
1508 // ...and see if this one excludes us.
1509 if (find(exc.begin(), exc.end(), modName) != exc.end()) {
1511 LYXERR(Debug::TCLASS, "Default module `" << modName <<
1512 "' not added because excluded by loaded module `" <<
1518 LYXERR(Debug::TCLASS, "Default module `" << modName << "' added.");
1519 layoutModules_.push_back(modName);
1526 LayoutFile const * BufferParams::baseClass() const
1528 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1529 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1535 LayoutFileIndex const & BufferParams::baseClassID() const
1537 return pimpl_->baseClass_;
1541 void BufferParams::makeDocumentClass()
1546 doc_class_ = &(DocumentClassBundle::get().newClass(*baseClass()));
1548 // FIXME It might be worth loading the children's modules here,
1549 // just as we load their bibliographies and such, instead of just
1550 // doing a check in InsetInclude.
1551 LayoutModuleList::const_iterator it = layoutModules_.begin();
1552 for (; it != layoutModules_.end(); it++) {
1553 string const modName = *it;
1554 LyXModule * lm = moduleList[modName];
1556 docstring const msg =
1557 bformat(_("The module %1$s has been requested by\n"
1558 "this document but has not been found in the list of\n"
1559 "available modules. If you recently installed it, you\n"
1560 "probably need to reconfigure LyX.\n"), from_utf8(modName));
1561 frontend::Alert::warning(_("Module not available"),
1562 msg + _("Some layouts may not be available."));
1563 LYXERR0("BufferParams::makeDocumentClass(): Module " <<
1564 modName << " requested but not found in module list.");
1567 if (!lm->isAvailable()) {
1568 docstring const msg =
1569 bformat(_("The module %1$s requires a package that is\n"
1570 "not available in your LaTeX installation. LaTeX output\n"
1571 "may not be possible.\n"), from_utf8(modName));
1572 frontend::Alert::warning(_("Package not available"), msg);
1574 FileName layout_file = libFileSearch("layouts", lm->getFilename());
1575 if (!doc_class_->read(layout_file, TextClass::MODULE)) {
1576 docstring const msg =
1577 bformat(_("Error reading module %1$s\n"), from_utf8(modName));
1578 frontend::Alert::warning(_("Read Error"), msg);
1581 if (!local_layout.empty()) {
1582 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1583 docstring const msg = _("Error reading internal layout information");
1584 frontend::Alert::warning(_("Read Error"), msg);
1590 bool BufferParams::addLayoutModule(string const & modName)
1592 LayoutModuleList::const_iterator it = layoutModules_.begin();
1593 LayoutModuleList::const_iterator end = layoutModules_.end();
1594 for (; it != end; it++)
1597 layoutModules_.push_back(modName);
1602 Font const BufferParams::getFont() const
1604 FontInfo f = documentClass().defaultfont();
1605 if (fontsDefaultFamily == "rmdefault")
1606 f.setFamily(ROMAN_FAMILY);
1607 else if (fontsDefaultFamily == "sfdefault")
1608 f.setFamily(SANS_FAMILY);
1609 else if (fontsDefaultFamily == "ttdefault")
1610 f.setFamily(TYPEWRITER_FAMILY);
1611 return Font(f, language);
1615 void BufferParams::readPreamble(Lexer & lex)
1617 if (lex.getString() != "\\begin_preamble")
1618 lyxerr << "Error (BufferParams::readPreamble):"
1619 "consistency check failed." << endl;
1621 preamble = lex.getLongString("\\end_preamble");
1625 void BufferParams::readLocalLayout(Lexer & lex)
1627 if (lex.getString() != "\\begin_local_layout")
1628 lyxerr << "Error (BufferParams::readLocalLayout):"
1629 "consistency check failed." << endl;
1631 local_layout = lex.getLongString("\\end_local_layout");
1635 void BufferParams::readLanguage(Lexer & lex)
1637 if (!lex.next()) return;
1639 string const tmptok = lex.getString();
1641 // check if tmptok is part of tex_babel in tex-defs.h
1642 language = languages.getLanguage(tmptok);
1644 // Language tmptok was not found
1645 language = default_language;
1646 lyxerr << "Warning: Setting language `"
1647 << tmptok << "' to `" << language->lang()
1653 void BufferParams::readGraphicsDriver(Lexer & lex)
1658 string const tmptok = lex.getString();
1659 // check if tmptok is part of tex_graphics in tex_defs.h
1662 string const test = tex_graphics[n++];
1664 if (test == tmptok) {
1665 graphicsDriver = tmptok;
1670 "Warning: graphics driver `$$Token' not recognized!\n"
1671 " Setting graphics driver to `default'.\n");
1672 graphicsDriver = "default";
1679 void BufferParams::readBullets(Lexer & lex)
1684 int const index = lex.getInteger();
1686 int temp_int = lex.getInteger();
1687 user_defined_bullet(index).setFont(temp_int);
1688 temp_bullet(index).setFont(temp_int);
1690 user_defined_bullet(index).setCharacter(temp_int);
1691 temp_bullet(index).setCharacter(temp_int);
1693 user_defined_bullet(index).setSize(temp_int);
1694 temp_bullet(index).setSize(temp_int);
1698 void BufferParams::readBulletsLaTeX(Lexer & lex)
1700 // The bullet class should be able to read this.
1703 int const index = lex.getInteger();
1705 docstring const temp_str = lex.getDocString();
1707 user_defined_bullet(index).setText(temp_str);
1708 temp_bullet(index).setText(temp_str);
1712 void BufferParams::readModules(Lexer & lex)
1714 if (!lex.eatLine()) {
1715 lyxerr << "Error (BufferParams::readModules):"
1716 "Unexpected end of input." << endl;
1720 string mod = lex.getString();
1721 if (mod == "\\end_modules")
1723 addLayoutModule(mod);
1729 void BufferParams::readRemovedModules(Lexer & lex)
1731 if (!lex.eatLine()) {
1732 lyxerr << "Error (BufferParams::readRemovedModules):"
1733 "Unexpected end of input." << endl;
1737 string mod = lex.getString();
1738 if (mod == "\\end_removed_modules")
1740 removedModules_.insert(mod);
1743 // now we want to remove any removed modules that were previously
1744 // added. normally, that will be because default modules were added in
1745 // setBaseClass(), which gets called when \textclass is read at the
1746 // start of the read.
1747 set<string>::const_iterator rit = removedModules_.begin();
1748 set<string>::const_iterator const ren = removedModules_.end();
1749 for (; rit != ren; rit++) {
1750 LayoutModuleList::iterator const mit = layoutModules_.begin();
1751 LayoutModuleList::iterator const men = layoutModules_.end();
1752 LayoutModuleList::iterator found = find(mit, men, *rit);
1755 layoutModules_.erase(found);
1760 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1762 char real_papersize = papersize;
1763 if (real_papersize == PAPER_DEFAULT)
1764 real_papersize = lyxrc.default_papersize;
1766 switch (real_papersize) {
1768 // could be anything, so don't guess
1770 case PAPER_CUSTOM: {
1771 if (purpose == XDVI && !paperwidth.empty() &&
1772 !paperheight.empty()) {
1773 // heightxwidth<unit>
1774 string first = paperwidth;
1775 string second = paperheight;
1776 if (orientation == ORIENTATION_LANDSCAPE)
1779 return first.erase(first.length() - 2)
1791 // dvips and dvipdfm do not know this
1792 if (purpose == DVIPS || purpose == DVIPDFM)
1796 // dvipdfm does not know this
1797 if (purpose == DVIPDFM)
1801 // dvipdfm does not know this
1802 if (purpose == DVIPDFM)
1805 case PAPER_USEXECUTIVE:
1806 // dvipdfm does not know this
1807 if (purpose == DVIPDFM)
1812 case PAPER_USLETTER:
1814 if (purpose == XDVI)
1821 string const BufferParams::dvips_options() const
1826 && papersize == PAPER_CUSTOM
1827 && !lyxrc.print_paper_dimension_flag.empty()
1828 && !paperwidth.empty()
1829 && !paperheight.empty()) {
1830 // using a custom papersize
1831 result = lyxrc.print_paper_dimension_flag;
1832 result += ' ' + paperwidth;
1833 result += ',' + paperheight;
1835 string const paper_option = paperSizeName(DVIPS);
1836 if (!paper_option.empty() && (paper_option != "letter" ||
1837 orientation != ORIENTATION_LANDSCAPE)) {
1838 // dvips won't accept -t letter -t landscape.
1839 // In all other cases, include the paper size
1841 result = lyxrc.print_paper_flag;
1842 result += ' ' + paper_option;
1845 if (orientation == ORIENTATION_LANDSCAPE &&
1846 papersize != PAPER_CUSTOM)
1847 result += ' ' + lyxrc.print_landscape_flag;
1852 string BufferParams::babelCall(string const & lang_opts) const
1854 string lang_pack = lyxrc.language_package;
1855 if (lang_pack != "\\usepackage{babel}")
1857 // suppress the babel call when there is no babel language defined
1858 // for the document language in the lib/languages file and if no
1859 // other languages are used (lang_opts is then empty)
1860 if (lang_opts.empty())
1862 // If Vietnamese is used, babel must directly be loaded with the
1863 // language options, see
1864 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1865 size_t viet = lang_opts.find("vietnam");
1866 // viet = string::npos when not found
1867 // If Japanese is used, babel must directly be loaded with the
1868 // language options, see
1869 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1870 size_t japan = lang_opts.find("japanese");
1871 // japan = string::npos when not found
1872 if (!lyxrc.language_global_options || viet != string::npos || japan != string::npos)
1873 return "\\usepackage[" + lang_opts + "]{babel}";
1878 void BufferParams::writeEncodingPreamble(odocstream & os,
1879 LaTeXFeatures & features, TexRow & texrow) const
1881 if (inputenc == "auto") {
1882 string const doc_encoding =
1883 language->encoding()->latexName();
1884 Encoding::Package const package =
1885 language->encoding()->package();
1887 // Create a list with all the input encodings used
1889 set<string> encodings =
1890 features.getEncodingSet(doc_encoding);
1892 // If the "japanese" package (i.e. pLaTeX) is used,
1893 // inputenc must be omitted.
1894 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1895 if (package == Encoding::japanese)
1896 features.require("japanese");
1898 if ((!encodings.empty() || package == Encoding::inputenc)
1899 && !features.isRequired("japanese")) {
1900 os << "\\usepackage[";
1901 set<string>::const_iterator it = encodings.begin();
1902 set<string>::const_iterator const end = encodings.end();
1904 os << from_ascii(*it);
1907 for (; it != end; ++it)
1908 os << ',' << from_ascii(*it);
1909 if (package == Encoding::inputenc) {
1910 if (!encodings.empty())
1912 os << from_ascii(doc_encoding);
1914 os << "]{inputenc}\n";
1917 if (package == Encoding::CJK || features.mustProvide("CJK")) {
1918 os << "\\usepackage{CJK}\n";
1921 } else if (inputenc != "default") {
1922 switch (encoding().package()) {
1923 case Encoding::none:
1924 case Encoding::japanese:
1926 case Encoding::inputenc:
1927 // do not load inputenc if japanese is used
1928 if (features.isRequired("japanese"))
1930 os << "\\usepackage[" << from_ascii(inputenc)
1935 os << "\\usepackage{CJK}\n";
1941 // The encoding "armscii8" (for Armenian) is only available when
1942 // the package "armtex" is loaded.
1943 if (language->encoding()->latexName() == "armscii8"
1944 || inputenc == "armscii8") {
1945 os << "\\usepackage{armtex}\n";
1951 string const BufferParams::loadFonts(string const & rm,
1952 string const & sf, string const & tt,
1953 bool const & sc, bool const & osf,
1954 int const & sfscale, int const & ttscale) const
1956 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1957 several packages have been replaced by others, that might not
1958 be installed on every system. We have to take care for that
1959 (see psnfss.pdf). We try to support all psnfss fonts as well
1960 as the fonts that have become de facto standard in the LaTeX
1961 world (e.g. Latin Modern). We do not support obsolete fonts
1962 (like PSLatex). In general, it should be possible to mix any
1963 rm font with any sf or tt font, respectively. (JSpitzm)
1965 -- separate math fonts.
1968 if (rm == "default" && sf == "default" && tt == "default")
1975 // Computer Modern (must be explicitely selectable -- there might be classes
1976 // that define a different default font!
1978 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1979 // osf for Computer Modern needs eco.sty
1981 os << "\\usepackage{eco}\n";
1983 // Latin Modern Roman
1984 else if (rm == "lmodern")
1985 os << "\\usepackage{lmodern}\n";
1987 else if (rm == "ae") {
1988 // not needed when using OT1 font encoding.
1989 if (lyxrc.fontenc != "default")
1990 os << "\\usepackage{ae,aecompl}\n";
1993 else if (rm == "times") {
1994 // try to load the best available package
1995 if (LaTeXFeatures::isAvailable("mathptmx"))
1996 os << "\\usepackage{mathptmx}\n";
1997 else if (LaTeXFeatures::isAvailable("mathptm"))
1998 os << "\\usepackage{mathptm}\n";
2000 os << "\\usepackage{times}\n";
2003 else if (rm == "palatino") {
2004 // try to load the best available package
2005 if (LaTeXFeatures::isAvailable("mathpazo")) {
2006 os << "\\usepackage";
2012 // "osf" includes "sc"!
2016 os << "{mathpazo}\n";
2018 else if (LaTeXFeatures::isAvailable("mathpple"))
2019 os << "\\usepackage{mathpple}\n";
2021 os << "\\usepackage{palatino}\n";
2024 else if (rm == "utopia") {
2025 // fourier supersedes utopia.sty, but does
2026 // not work with OT1 encoding.
2027 if (LaTeXFeatures::isAvailable("fourier")
2028 && lyxrc.fontenc != "default") {
2029 os << "\\usepackage";
2040 os << "{fourier}\n";
2043 os << "\\usepackage{utopia}\n";
2045 // Bera (complete fontset)
2046 else if (rm == "bera" && sf == "default" && tt == "default")
2047 os << "\\usepackage{bera}\n";
2049 else if (rm != "default")
2050 os << "\\usepackage" << "{" << rm << "}\n";
2053 // Helvetica, Bera Sans
2054 if (sf == "helvet" || sf == "berasans") {
2056 os << "\\usepackage[scaled=" << float(sfscale) / 100
2057 << "]{" << sf << "}\n";
2059 os << "\\usepackage{" << sf << "}\n";
2062 else if (sf == "avant")
2063 os << "\\usepackage{" << sf << "}\n";
2064 // Computer Modern, Latin Modern, CM Bright
2065 else if (sf != "default")
2066 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2068 // monospaced/typewriter
2069 // Courier, LuxiMono
2070 if (tt == "luximono" || tt == "beramono") {
2072 os << "\\usepackage[scaled=" << float(ttscale) / 100
2073 << "]{" << tt << "}\n";
2075 os << "\\usepackage{" << tt << "}\n";
2078 else if (tt == "courier" )
2079 os << "\\usepackage{" << tt << "}\n";
2080 // Computer Modern, Latin Modern, CM Bright
2081 else if (tt != "default")
2082 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2088 Encoding const & BufferParams::encoding() const
2090 if (inputenc == "auto" || inputenc == "default")
2091 return *language->encoding();
2092 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2095 LYXERR0("Unknown inputenc value `" << inputenc
2096 << "'. Using `auto' instead.");
2097 return *language->encoding();
2101 CiteEngine BufferParams::citeEngine() const
2103 // FIXME the class should provide the numerical/
2104 // authoryear choice
2105 if (documentClass().provides("natbib")
2106 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2107 return ENGINE_NATBIB_AUTHORYEAR;
2108 return cite_engine_;
2112 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2114 cite_engine_ = cite_engine;