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",
102 // Paragraph separation
103 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
106 ParSepTranslator const init_parseptranslator()
108 ParSepTranslator translator
109 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
110 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
115 ParSepTranslator const & parseptranslator()
117 static ParSepTranslator translator = init_parseptranslator();
123 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
126 QuotesLangTranslator const init_quoteslangtranslator()
128 QuotesLangTranslator translator
129 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
130 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
131 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
132 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
133 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
134 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
139 QuotesLangTranslator const & quoteslangtranslator()
141 static QuotesLangTranslator translator = init_quoteslangtranslator();
147 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
150 static PaperSizeTranslator initPaperSizeTranslator()
152 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
153 translator.addPair(string_papersize[1], PAPER_CUSTOM);
154 translator.addPair(string_papersize[2], PAPER_USLETTER);
155 translator.addPair(string_papersize[3], PAPER_USLEGAL);
156 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
157 translator.addPair(string_papersize[5], PAPER_A3);
158 translator.addPair(string_papersize[6], PAPER_A4);
159 translator.addPair(string_papersize[7], PAPER_A5);
160 translator.addPair(string_papersize[8], PAPER_B3);
161 translator.addPair(string_papersize[9], PAPER_B4);
162 translator.addPair(string_papersize[10], PAPER_B5);
167 PaperSizeTranslator const & papersizetranslator()
169 static PaperSizeTranslator translator = initPaperSizeTranslator();
175 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
178 PaperOrientationTranslator const init_paperorientationtranslator()
180 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
181 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
186 PaperOrientationTranslator const & paperorientationtranslator()
188 static PaperOrientationTranslator translator = init_paperorientationtranslator();
194 typedef Translator<int, PageSides> SidesTranslator;
197 SidesTranslator const init_sidestranslator()
199 SidesTranslator translator(1, OneSide);
200 translator.addPair(2, TwoSides);
205 SidesTranslator const & sidestranslator()
207 static SidesTranslator translator = init_sidestranslator();
213 typedef Translator<int, BufferParams::Package> PackageTranslator;
216 PackageTranslator const init_packagetranslator()
218 PackageTranslator translator(0, BufferParams::package_off);
219 translator.addPair(1, BufferParams::package_auto);
220 translator.addPair(2, BufferParams::package_on);
225 PackageTranslator const & packagetranslator()
227 static PackageTranslator translator = init_packagetranslator();
233 typedef Translator<string, CiteEngine> CiteEngineTranslator;
236 CiteEngineTranslator const init_citeenginetranslator()
238 CiteEngineTranslator translator("basic", ENGINE_BASIC);
239 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
240 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
241 translator.addPair("jurabib", ENGINE_JURABIB);
246 CiteEngineTranslator const & citeenginetranslator()
248 static CiteEngineTranslator translator = init_citeenginetranslator();
254 typedef Translator<string, Spacing::Space> SpaceTranslator;
257 SpaceTranslator const init_spacetranslator()
259 SpaceTranslator translator("default", Spacing::Default);
260 translator.addPair("single", Spacing::Single);
261 translator.addPair("onehalf", Spacing::Onehalf);
262 translator.addPair("double", Spacing::Double);
263 translator.addPair("other", Spacing::Other);
268 SpaceTranslator const & spacetranslator()
270 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";
350 fontsSansScale = 100;
351 fontsTypewriterScale = 100;
353 graphicsDriver = "default";
356 listings_params = string();
357 pagestyle = "default";
359 for (int iter = 0; iter < 4; ++iter) {
360 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
361 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
366 docstring BufferParams::B_(string const & l10n) const
368 LASSERT(language, /**/);
369 return getMessages(language->code()).get(l10n);
373 AuthorList & BufferParams::authors()
375 return pimpl_->authorlist;
379 AuthorList const & BufferParams::authors() const
381 return pimpl_->authorlist;
385 BranchList & BufferParams::branchlist()
387 return pimpl_->branchlist;
391 BranchList const & BufferParams::branchlist() const
393 return pimpl_->branchlist;
397 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
399 LASSERT(index < 4, /**/);
400 return pimpl_->temp_bullets[index];
404 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
406 LASSERT(index < 4, /**/);
407 return pimpl_->temp_bullets[index];
411 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
413 LASSERT(index < 4, /**/);
414 return pimpl_->user_defined_bullets[index];
418 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
420 LASSERT(index < 4, /**/);
421 return pimpl_->user_defined_bullets[index];
425 Spacing & BufferParams::spacing()
427 return pimpl_->spacing;
431 Spacing const & BufferParams::spacing() const
433 return pimpl_->spacing;
437 PDFOptions & BufferParams::pdfoptions()
439 return pimpl_->pdfoptions;
443 PDFOptions const & BufferParams::pdfoptions() const
445 return pimpl_->pdfoptions;
449 VSpace const & BufferParams::getDefSkip() const
451 return pimpl_->defskip;
455 void BufferParams::setDefSkip(VSpace const & vs)
457 pimpl_->defskip = vs;
461 string BufferParams::readToken(Lexer & lex, string const & token,
462 FileName const & filepath)
464 if (token == "\\textclass") {
466 string const classname = lex.getString();
467 // if there exists a local layout file, ignore the system one
468 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
470 LayoutFileList & bcl = LayoutFileList::get();
471 if (tcp.empty() && !filepath.empty())
472 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
476 setBaseClass(classname);
477 // We assume that a tex class exists for local or unknown layouts so this warning
478 // will only be given for system layouts.
479 if (!baseClass()->isTeXClassAvailable()) {
480 docstring const msg =
481 bformat(_("The layout file requested by this document,\n"
483 "is not usable. This is probably because a LaTeX\n"
484 "class or style file required by it is not\n"
485 "available. See the Customization documentation\n"
486 "for more information.\n"), from_utf8(classname));
487 frontend::Alert::warning(_("Document class not available"),
488 msg + _("LyX will not be able to produce output."));
490 } else if (token == "\\begin_preamble") {
492 } else if (token == "\\begin_local_layout") {
493 readLocalLayout(lex);
494 } else if (token == "\\begin_modules") {
496 } else if (token == "\\begin_removed_modules") {
497 readRemovedModules(lex);
498 } else if (token == "\\options") {
500 options = lex.getString();
501 } else if (token == "\\use_default_options") {
502 lex >> use_default_options;
503 } else if (token == "\\master") {
505 master = lex.getString();
506 } else if (token == "\\language") {
508 } else if (token == "\\inputencoding") {
510 } else if (token == "\\graphics") {
511 readGraphicsDriver(lex);
512 } else if (token == "\\font_roman") {
514 fontsRoman = lex.getString();
515 } else if (token == "\\font_sans") {
517 fontsSans = lex.getString();
518 } else if (token == "\\font_typewriter") {
520 fontsTypewriter = lex.getString();
521 } else if (token == "\\font_default_family") {
522 lex >> fontsDefaultFamily;
523 } else if (token == "\\use_xetex") {
525 } else if (token == "\\font_sc") {
527 } else if (token == "\\font_osf") {
529 } else if (token == "\\font_sf_scale") {
530 lex >> fontsSansScale;
531 } else if (token == "\\font_tt_scale") {
532 lex >> fontsTypewriterScale;
533 } else if (token == "\\font_cjk") {
535 } else if (token == "\\paragraph_separation") {
538 paragraph_separation = parseptranslator().find(parsep);
539 } else if (token == "\\defskip") {
541 string defskip = lex.getString();
542 if (defskip == "defskip")
545 pimpl_->defskip = VSpace(defskip);
546 } else if (token == "\\quotes_language") {
549 quotes_language = quoteslangtranslator().find(quotes_lang);
550 } else if (token == "\\papersize") {
553 papersize = papersizetranslator().find(ppsize);
554 } else if (token == "\\use_geometry") {
556 } else if (token == "\\use_amsmath") {
559 use_amsmath = packagetranslator().find(use_ams);
560 } else if (token == "\\use_esint") {
563 use_esint = packagetranslator().find(useesint);
564 } else if (token == "\\cite_engine") {
567 cite_engine_ = citeenginetranslator().find(engine);
568 } else if (token == "\\use_bibtopic") {
570 } else if (token == "\\tracking_changes") {
572 } else if (token == "\\output_changes") {
573 lex >> outputChanges;
574 } else if (token == "\\branch") {
576 docstring branch = lex.getDocString();
577 branchlist().add(branch);
580 string const tok = lex.getString();
581 if (tok == "\\end_branch")
583 Branch * branch_ptr = branchlist().find(branch);
584 if (tok == "\\selected") {
587 branch_ptr->setSelected(lex.getInteger());
589 // not yet operational
590 if (tok == "\\color") {
592 string color = lex.getString();
594 branch_ptr->setColor(color);
595 // Update also the Color table:
597 color = lcolor.getX11Name(Color_background);
599 lcolor.setColor(to_utf8(branch), color);
603 } else if (token == "\\author") {
605 istringstream ss(lex.getString());
608 author_map.push_back(pimpl_->authorlist.record(a));
609 } else if (token == "\\paperorientation") {
612 orientation = paperorientationtranslator().find(orient);
613 } else if (token == "\\paperwidth") {
615 } else if (token == "\\paperheight") {
617 } else if (token == "\\leftmargin") {
619 } else if (token == "\\topmargin") {
621 } else if (token == "\\rightmargin") {
623 } else if (token == "\\bottommargin") {
625 } else if (token == "\\headheight") {
627 } else if (token == "\\headsep") {
629 } else if (token == "\\footskip") {
631 } else if (token == "\\columnsep") {
633 } else if (token == "\\paperfontsize") {
635 } else if (token == "\\papercolumns") {
637 } else if (token == "\\listings_params") {
640 listings_params = InsetListingsParams(par).params();
641 } else if (token == "\\papersides") {
644 sides = sidestranslator().find(psides);
645 } else if (token == "\\paperpagestyle") {
647 } else if (token == "\\bullet") {
649 } else if (token == "\\bulletLaTeX") {
650 readBulletsLaTeX(lex);
651 } else if (token == "\\secnumdepth") {
653 } else if (token == "\\tocdepth") {
655 } else if (token == "\\spacing") {
659 if (nspacing == "other") {
662 spacing().set(spacetranslator().find(nspacing), tmp_val);
663 } else if (token == "\\float_placement") {
664 lex >> float_placement;
666 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
667 string toktmp = pdfoptions().readToken(lex, token);
668 if (!toktmp.empty()) {
669 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
674 lyxerr << "BufferParams::readToken(): Unknown token: " <<
683 void BufferParams::writeFile(ostream & os) const
685 // The top of the file is written by the buffer.
686 // Prints out the buffer info into the .lyx file given by file
689 os << "\\textclass " << baseClass()->name() << '\n';
692 if (!preamble.empty()) {
693 // remove '\n' from the end of preamble
694 string const tmppreamble = rtrim(preamble, "\n");
695 os << "\\begin_preamble\n"
697 << "\n\\end_preamble\n";
701 if (!options.empty()) {
702 os << "\\options " << options << '\n';
705 // use the class options defined in the layout?
706 os << "\\use_default_options "
707 << convert<string>(use_default_options) << "\n";
709 // the master document
710 if (!master.empty()) {
711 os << "\\master " << master << '\n';
715 if (!removedModules_.empty()) {
716 os << "\\begin_removed_modules" << '\n';
717 list<string>::const_iterator it = removedModules_.begin();
718 list<string>::const_iterator en = removedModules_.end();
719 for (; it != en; it++)
721 os << "\\end_removed_modules" << '\n';
725 if (!layoutModules_.empty()) {
726 os << "\\begin_modules" << '\n';
727 LayoutModuleList::const_iterator it = layoutModules_.begin();
728 LayoutModuleList::const_iterator en = layoutModules_.end();
729 for (; it != en; it++)
731 os << "\\end_modules" << '\n';
734 // local layout information
735 if (!local_layout.empty()) {
736 // remove '\n' from the end
737 string const tmplocal = rtrim(local_layout, "\n");
738 os << "\\begin_local_layout\n"
740 << "\n\\end_local_layout\n";
743 // then the text parameters
744 if (language != ignore_language)
745 os << "\\language " << language->lang() << '\n';
746 os << "\\inputencoding " << inputenc
747 << "\n\\font_roman " << fontsRoman
748 << "\n\\font_sans " << fontsSans
749 << "\n\\font_typewriter " << fontsTypewriter
750 << "\n\\font_default_family " << fontsDefaultFamily
751 << "\n\\use_xetex " << convert<string>(useXetex)
752 << "\n\\font_sc " << convert<string>(fontsSC)
753 << "\n\\font_osf " << convert<string>(fontsOSF)
754 << "\n\\font_sf_scale " << fontsSansScale
755 << "\n\\font_tt_scale " << fontsTypewriterScale
757 if (!fontsCJK.empty()) {
758 os << "\\font_cjk " << fontsCJK << '\n';
760 os << "\n\\graphics " << graphicsDriver << '\n';
762 if (!float_placement.empty()) {
763 os << "\\float_placement " << float_placement << '\n';
765 os << "\\paperfontsize " << fontsize << '\n';
767 spacing().writeFile(os);
768 pdfoptions().writeFile(os);
770 os << "\\papersize " << string_papersize[papersize]
771 << "\n\\use_geometry " << convert<string>(use_geometry)
772 << "\n\\use_amsmath " << use_amsmath
773 << "\n\\use_esint " << use_esint
774 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
775 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
776 << "\n\\paperorientation " << string_orientation[orientation]
779 BranchList::const_iterator it = branchlist().begin();
780 BranchList::const_iterator end = branchlist().end();
781 for (; it != end; ++it) {
782 os << "\\branch " << to_utf8(it->branch())
783 << "\n\\selected " << it->isSelected()
784 << "\n\\color " << lyx::X11hexname(it->color())
789 if (!paperwidth.empty())
790 os << "\\paperwidth "
791 << VSpace(paperwidth).asLyXCommand() << '\n';
792 if (!paperheight.empty())
793 os << "\\paperheight "
794 << VSpace(paperheight).asLyXCommand() << '\n';
795 if (!leftmargin.empty())
796 os << "\\leftmargin "
797 << VSpace(leftmargin).asLyXCommand() << '\n';
798 if (!topmargin.empty())
800 << VSpace(topmargin).asLyXCommand() << '\n';
801 if (!rightmargin.empty())
802 os << "\\rightmargin "
803 << VSpace(rightmargin).asLyXCommand() << '\n';
804 if (!bottommargin.empty())
805 os << "\\bottommargin "
806 << VSpace(bottommargin).asLyXCommand() << '\n';
807 if (!headheight.empty())
808 os << "\\headheight "
809 << VSpace(headheight).asLyXCommand() << '\n';
810 if (!headsep.empty())
812 << VSpace(headsep).asLyXCommand() << '\n';
813 if (!footskip.empty())
815 << VSpace(footskip).asLyXCommand() << '\n';
816 if (!columnsep.empty())
818 << VSpace(columnsep).asLyXCommand() << '\n';
819 os << "\\secnumdepth " << secnumdepth
820 << "\n\\tocdepth " << tocdepth
821 << "\n\\paragraph_separation "
822 << string_paragraph_separation[paragraph_separation]
823 << "\n\\defskip " << getDefSkip().asLyXCommand()
824 << "\n\\quotes_language "
825 << string_quotes_language[quotes_language]
826 << "\n\\papercolumns " << columns
827 << "\n\\papersides " << sides
828 << "\n\\paperpagestyle " << pagestyle << '\n';
829 if (!listings_params.empty())
830 os << "\\listings_params \"" <<
831 InsetListingsParams(listings_params).encodedString() << "\"\n";
832 for (int i = 0; i < 4; ++i) {
833 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
834 if (user_defined_bullet(i).getFont() != -1) {
835 os << "\\bullet " << i << " "
836 << user_defined_bullet(i).getFont() << " "
837 << user_defined_bullet(i).getCharacter() << " "
838 << user_defined_bullet(i).getSize() << "\n";
842 os << "\\bulletLaTeX " << i << " \""
843 << lyx::to_ascii(user_defined_bullet(i).getText())
849 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
850 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
852 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
853 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
854 for (; a_it != a_end; ++a_it) {
855 if (a_it->second.used())
856 os << "\\author " << a_it->second << "\n";
858 os << "\\author " << Author() << "\n";
863 void BufferParams::validate(LaTeXFeatures & features) const
865 features.require(documentClass().requires());
868 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
869 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
870 LaTeXFeatures::isAvailable("xcolor");
872 switch (features.runparams().flavor) {
873 case OutputParams::LATEX:
875 features.require("ct-dvipost");
876 features.require("dvipost");
877 } else if (xcolorulem) {
878 features.require("ct-xcolor-ulem");
879 features.require("ulem");
880 features.require("xcolor");
882 features.require("ct-none");
885 case OutputParams::PDFLATEX:
886 case OutputParams::XETEX:
888 features.require("ct-xcolor-ulem");
889 features.require("ulem");
890 features.require("xcolor");
891 // improves color handling in PDF output
892 features.require("pdfcolmk");
894 features.require("ct-none");
902 // Floats with 'Here definitely' as default setting.
903 if (float_placement.find('H') != string::npos)
904 features.require("float");
906 // AMS Style is at document level
907 if (use_amsmath == package_on
908 || documentClass().provides("amsmath"))
909 features.require("amsmath");
910 if (use_esint == package_on)
911 features.require("esint");
913 // Document-level line spacing
914 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
915 features.require("setspace");
917 // the bullet shapes are buffer level not paragraph level
918 // so they are tested here
919 for (int i = 0; i < 4; ++i) {
920 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
922 int const font = user_defined_bullet(i).getFont();
924 int const c = user_defined_bullet(i).getCharacter();
930 features.require("latexsym");
932 } else if (font == 1) {
933 features.require("amssymb");
934 } else if (font >= 2 && font <= 5) {
935 features.require("pifont");
939 if (pdfoptions().use_hyperref) {
940 features.require("hyperref");
941 // due to interferences with babel and hyperref, the color package has to
942 // be loaded after hyperref when hyperref is used with the colorlinks
943 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
944 if (pdfoptions().colorlinks)
945 features.require("color");
949 features.require("xetex");
951 if (language->lang() == "vietnamese")
952 features.require("vietnamese");
953 else if (language->lang() == "japanese")
954 features.require("japanese");
958 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
959 TexRow & texrow) const
961 os << "\\documentclass";
963 DocumentClass const & tclass = documentClass();
965 ostringstream clsoptions; // the document class options.
967 if (tokenPos(tclass.opt_fontsize(),
968 '|', fontsize) >= 0) {
969 // only write if existing in list (and not default)
970 clsoptions << fontsize << "pt,";
973 // custom, A3, B3 and B4 paper sizes need geometry
974 bool nonstandard_papersize = papersize == PAPER_B3
975 || papersize == PAPER_B4
976 || papersize == PAPER_A3
977 || papersize == PAPER_CUSTOM;
982 clsoptions << "a4paper,";
985 clsoptions << "letterpaper,";
988 clsoptions << "a5paper,";
991 clsoptions << "b5paper,";
993 case PAPER_USEXECUTIVE:
994 clsoptions << "executivepaper,";
997 clsoptions << "legalpaper,";
1009 if (sides != tclass.sides()) {
1012 clsoptions << "oneside,";
1015 clsoptions << "twoside,";
1021 if (columns != tclass.columns()) {
1023 clsoptions << "twocolumn,";
1025 clsoptions << "onecolumn,";
1029 && orientation == ORIENTATION_LANDSCAPE)
1030 clsoptions << "landscape,";
1032 // language should be a parameter to \documentclass
1033 if (language->babel() == "hebrew"
1034 && default_language->babel() != "hebrew")
1035 // This seems necessary
1036 features.useLanguage(default_language);
1038 ostringstream language_options;
1039 bool const use_babel = features.useBabel();
1041 language_options << features.getLanguages();
1042 if (!language->babel().empty()) {
1043 if (!language_options.str().empty())
1044 language_options << ',';
1045 language_options << language->babel();
1047 // if Vietnamese is used, babel must directly be loaded
1048 // with language options, not in the class options, see
1049 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1050 size_t viet = language_options.str().find("vietnam");
1051 // viet = string::npos when not found
1052 // the same is for all other languages that are not directly supported by
1053 // babel, but where LaTeX-packages add babel support.
1054 // this is currently the case for Latvian, Lithuanian, and Mongolian
1055 size_t latvian = language_options.str().find("latvian");
1056 size_t lithu = language_options.str().find("lithuanian");
1057 size_t mongo = language_options.str().find("mongolian");
1058 // if Japanese is used, babel must directly be loaded
1059 // with language options, not in the class options, see
1060 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1061 size_t japan = language_options.str().find("japanese");
1062 if (lyxrc.language_global_options && !language_options.str().empty()
1063 && viet == string::npos && japan == string::npos
1064 && latvian == string::npos && lithu == string::npos
1065 && mongo == string::npos)
1066 clsoptions << language_options.str() << ',';
1069 // the predefined options from the layout
1070 if (use_default_options && !tclass.options().empty())
1071 clsoptions << tclass.options() << ',';
1073 // the user-defined options
1074 if (!options.empty()) {
1075 clsoptions << options << ',';
1078 string strOptions(clsoptions.str());
1079 if (!strOptions.empty()) {
1080 strOptions = rtrim(strOptions, ",");
1082 os << '[' << from_utf8(strOptions) << ']';
1085 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1087 // end of \documentclass defs
1090 os << "\\usepackage{fontspec}\n";
1092 os << "\\usepackage{xunicode}\n";
1094 os << "\\usepackage{xltxtra}\n";
1098 // font selection must be done before loading fontenc.sty
1099 string const fonts =
1100 loadFonts(fontsRoman, fontsSans,
1101 fontsTypewriter, fontsSC, fontsOSF,
1102 fontsSansScale, fontsTypewriterScale, useXetex);
1103 if (!fonts.empty()) {
1104 os << from_ascii(fonts);
1107 if (fontsDefaultFamily != "default")
1108 os << "\\renewcommand{\\familydefault}{\\"
1109 << from_ascii(fontsDefaultFamily) << "}\n";
1111 // set font encoding
1112 // this one is not per buffer
1113 // for arabic_arabi and farsi we also need to load the LAE and
1115 // XeteX works without fontenc
1116 if (lyxrc.fontenc != "default" && language->lang() != "japanese"
1118 if (language->lang() == "arabic_arabi"
1119 || language->lang() == "farsi") {
1120 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1121 << ",LFE,LAE]{fontenc}\n";
1124 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1130 // handle inputenc etc.
1131 writeEncodingPreamble(os, features, texrow);
1133 if (!listings_params.empty() || features.isRequired("listings")) {
1134 os << "\\usepackage{listings}\n";
1137 if (!listings_params.empty()) {
1139 // do not test validity because listings_params is
1140 // supposed to be valid
1142 InsetListingsParams(listings_params).separatedParams(true);
1143 // we can't support all packages, but we should load the color package
1144 if (par.find("\\color", 0) != string::npos)
1145 features.require("color");
1146 os << from_utf8(par);
1147 // count the number of newlines
1148 for (size_t i = 0; i < par.size(); ++i)
1154 if (!tclass.provides("geometry")
1155 && (use_geometry || nonstandard_papersize)) {
1156 odocstringstream ods;
1157 if (!getGraphicsDriver("geometry").empty())
1158 ods << getGraphicsDriver("geometry");
1159 if (orientation == ORIENTATION_LANDSCAPE)
1160 ods << ",landscape";
1161 switch (papersize) {
1163 if (!paperwidth.empty())
1164 ods << ",paperwidth="
1165 << from_ascii(paperwidth);
1166 if (!paperheight.empty())
1167 ods << ",paperheight="
1168 << from_ascii(paperheight);
1170 case PAPER_USLETTER:
1171 ods << ",letterpaper";
1174 ods << ",legalpaper";
1176 case PAPER_USEXECUTIVE:
1177 ods << ",executivepaper";
1198 // default papersize ie PAPER_DEFAULT
1199 switch (lyxrc.default_papersize) {
1200 case PAPER_DEFAULT: // keep compiler happy
1201 case PAPER_USLETTER:
1202 ods << ",letterpaper";
1205 ods << ",legalpaper";
1207 case PAPER_USEXECUTIVE:
1208 ods << ",executivepaper";
1228 docstring const g_options = trim(ods.str(), ",");
1229 os << "\\usepackage";
1230 if (!g_options.empty())
1231 os << '[' << g_options << ']';
1232 os << "{geometry}\n";
1234 os << "\\geometry{verbose";
1235 if (!topmargin.empty())
1236 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1237 if (!bottommargin.empty())
1238 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1239 if (!leftmargin.empty())
1240 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1241 if (!rightmargin.empty())
1242 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1243 if (!headheight.empty())
1244 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1245 if (!headsep.empty())
1246 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1247 if (!footskip.empty())
1248 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1249 if (!columnsep.empty())
1250 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1253 } else if (orientation == ORIENTATION_LANDSCAPE) {
1254 features.require("papersize");
1257 if (tokenPos(tclass.opt_pagestyle(),
1258 '|', pagestyle) >= 0) {
1259 if (pagestyle == "fancy") {
1260 os << "\\usepackage{fancyhdr}\n";
1263 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1267 // Only if class has a ToC hierarchy
1268 if (tclass.hasTocLevels()) {
1269 if (secnumdepth != tclass.secnumdepth()) {
1270 os << "\\setcounter{secnumdepth}{"
1275 if (tocdepth != tclass.tocdepth()) {
1276 os << "\\setcounter{tocdepth}{"
1283 if (paragraph_separation) {
1284 switch (getDefSkip().kind()) {
1285 case VSpace::SMALLSKIP:
1286 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1288 case VSpace::MEDSKIP:
1289 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1291 case VSpace::BIGSKIP:
1292 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1294 case VSpace::LENGTH:
1295 os << "\\setlength{\\parskip}{"
1296 << from_utf8(getDefSkip().length().asLatexString())
1299 default: // should never happen // Then delete it.
1300 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1305 os << "\\setlength{\\parindent}{0pt}\n";
1309 // Now insert the LyX specific LaTeX commands...
1310 docstring lyxpreamble;
1312 // due to interferences with babel and hyperref, the color package has to
1313 // be loaded (when it is not already loaded) before babel when hyperref
1314 // is used with the colorlinks option, see
1315 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1316 // we decided therefore to load color always before babel, see
1317 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1318 lyxpreamble += from_ascii(features.getColorOptions());
1320 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1322 && (features.isRequired("jurabib")
1323 || features.isRequired("hyperref")
1324 || features.isRequired("vietnamese")
1325 || features.isRequired("japanese") ) ) {
1327 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1328 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1331 // The optional packages;
1332 lyxpreamble += from_ascii(features.getPackages());
1335 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1338 // * Hyperref manual: "Make sure it comes last of your loaded
1339 // packages, to give it a fighting chance of not being over-written,
1340 // since its job is to redefine many LaTeX commands."
1341 // * Email from Heiko Oberdiek: "It is usually better to load babel
1342 // before hyperref. Then hyperref has a chance to detect babel.
1343 // * Has to be loaded before the "LyX specific LaTeX commands" to
1344 // avoid errors with algorithm floats.
1345 // use hyperref explicitely when it is required
1346 if (features.isRequired("hyperref")) {
1347 odocstringstream oss;
1348 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1349 lyxpreamble += oss.str();
1352 // Will be surrounded by \makeatletter and \makeatother when needed
1353 docstring atlyxpreamble;
1355 // Some macros LyX will need
1356 docstring tmppreamble(from_ascii(features.getMacros()));
1358 if (!tmppreamble.empty())
1359 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1360 "LyX specific LaTeX commands.\n"
1361 + tmppreamble + '\n';
1363 // the text class specific preamble
1364 tmppreamble = features.getTClassPreamble();
1365 if (!tmppreamble.empty())
1366 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1367 "Textclass specific LaTeX commands.\n"
1368 + tmppreamble + '\n';
1370 /* the user-defined preamble */
1371 if (!preamble.empty())
1373 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1374 "User specified LaTeX commands.\n"
1375 + from_utf8(preamble) + '\n';
1377 // subfig loads internally the LaTeX package "caption". As
1378 // caption is a very popular package, users will load it in
1379 // the preamble. Therefore we must load subfig behind the
1380 // user-defined preamble and check if the caption package was
1381 // loaded or not. For the case that caption is loaded before
1382 // subfig, there is the subfig option "caption=false". This
1383 // option also works when a koma-script class is used and
1384 // koma's own caption commands are used instead of caption. We
1385 // use \PassOptionsToPackage here because the user could have
1386 // already loaded subfig in the preamble.
1387 if (features.isRequired("subfig")) {
1388 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1389 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1390 "\\usepackage{subfig}\n";
1393 // Itemize bullet settings need to be last in case the user
1394 // defines their own bullets that use a package included
1395 // in the user-defined preamble -- ARRae
1396 // Actually it has to be done much later than that
1397 // since some packages like frenchb make modifications
1398 // at \begin{document} time -- JMarc
1399 docstring bullets_def;
1400 for (int i = 0; i < 4; ++i) {
1401 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1402 if (bullets_def.empty())
1403 bullets_def += "\\AtBeginDocument{\n";
1404 bullets_def += " \\def\\labelitemi";
1406 // `i' is one less than the item to modify
1413 bullets_def += "ii";
1419 bullets_def += '{' +
1420 user_defined_bullet(i).getText()
1425 if (!bullets_def.empty())
1426 atlyxpreamble += bullets_def + "}\n\n";
1428 if (atlyxpreamble.find(from_ascii("@")) != docstring::npos)
1429 lyxpreamble += "\n\\makeatletter\n"
1430 + atlyxpreamble + "\\makeatother\n\n";
1432 lyxpreamble += '\n' + atlyxpreamble;
1434 // We try to load babel late, in case it interferes with other packages.
1435 // Jurabib and Hyperref have to be called after babel, though.
1436 if (use_babel && !features.isRequired("jurabib")
1437 && !features.isRequired("hyperref")
1438 && !features.isRequired("vietnamese")
1439 && !features.isRequired("japanese")) {
1441 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1442 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1445 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1446 if (!i18npreamble.empty())
1447 lyxpreamble += i18npreamble + '\n';
1450 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1451 for (int j = 0; j != nlines; ++j) {
1460 void BufferParams::useClassDefaults()
1462 DocumentClass const & tclass = documentClass();
1464 sides = tclass.sides();
1465 columns = tclass.columns();
1466 pagestyle = tclass.pagestyle();
1467 use_default_options = true;
1468 // Only if class has a ToC hierarchy
1469 if (tclass.hasTocLevels()) {
1470 secnumdepth = tclass.secnumdepth();
1471 tocdepth = tclass.tocdepth();
1476 bool BufferParams::hasClassDefaults() const
1478 DocumentClass const & tclass = documentClass();
1480 return sides == tclass.sides()
1481 && columns == tclass.columns()
1482 && pagestyle == tclass.pagestyle()
1483 && use_default_options
1484 && secnumdepth == tclass.secnumdepth()
1485 && tocdepth == tclass.tocdepth();
1489 DocumentClass const & BufferParams::documentClass() const
1495 DocumentClass const * BufferParams::documentClassPtr() const {
1500 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1501 // evil, but this function is evil
1502 doc_class_ = const_cast<DocumentClass *>(tc);
1506 bool BufferParams::setBaseClass(string const & classname)
1508 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1509 LayoutFileList & bcl = LayoutFileList::get();
1510 if (!bcl.haveClass(classname)) {
1512 bformat(_("The document class %1$s could not be found. "
1513 "A default textclass with default layouts will be used. "
1514 "LyX might not be able to produce output unless a correct "
1515 "textclass is selected from the document settings dialog."),
1516 from_utf8(classname));
1517 frontend::Alert::error(_("Document class not found"), s);
1518 bcl.addEmptyClass(classname);
1521 bool const success = bcl[classname].load();
1524 bformat(_("The document class %1$s could not be loaded."),
1525 from_utf8(classname));
1526 frontend::Alert::error(_("Could not load class"), s);
1530 pimpl_->baseClass_ = classname;
1531 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1536 LayoutFile const * BufferParams::baseClass() const
1538 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1539 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1545 LayoutFileIndex const & BufferParams::baseClassID() const
1547 return pimpl_->baseClass_;
1551 void BufferParams::makeDocumentClass()
1556 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1558 if (!local_layout.empty()) {
1559 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1560 docstring const msg = _("Error reading internal layout information");
1561 frontend::Alert::warning(_("Read Error"), msg);
1566 bool BufferParams::moduleCanBeAdded(string const & modName) const
1568 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1572 bool BufferParams::addLayoutModule(string const & modName)
1574 LayoutModuleList::const_iterator it = layoutModules_.begin();
1575 LayoutModuleList::const_iterator end = layoutModules_.end();
1576 for (; it != end; it++)
1579 layoutModules_.push_back(modName);
1584 Font const BufferParams::getFont() const
1586 FontInfo f = documentClass().defaultfont();
1587 if (fontsDefaultFamily == "rmdefault")
1588 f.setFamily(ROMAN_FAMILY);
1589 else if (fontsDefaultFamily == "sfdefault")
1590 f.setFamily(SANS_FAMILY);
1591 else if (fontsDefaultFamily == "ttdefault")
1592 f.setFamily(TYPEWRITER_FAMILY);
1593 return Font(f, language);
1597 void BufferParams::readPreamble(Lexer & lex)
1599 if (lex.getString() != "\\begin_preamble")
1600 lyxerr << "Error (BufferParams::readPreamble):"
1601 "consistency check failed." << endl;
1603 preamble = lex.getLongString("\\end_preamble");
1607 void BufferParams::readLocalLayout(Lexer & lex)
1609 if (lex.getString() != "\\begin_local_layout")
1610 lyxerr << "Error (BufferParams::readLocalLayout):"
1611 "consistency check failed." << endl;
1613 local_layout = lex.getLongString("\\end_local_layout");
1617 void BufferParams::readLanguage(Lexer & lex)
1619 if (!lex.next()) return;
1621 string const tmptok = lex.getString();
1623 // check if tmptok is part of tex_babel in tex-defs.h
1624 language = languages.getLanguage(tmptok);
1626 // Language tmptok was not found
1627 language = default_language;
1628 lyxerr << "Warning: Setting language `"
1629 << tmptok << "' to `" << language->lang()
1635 void BufferParams::readGraphicsDriver(Lexer & lex)
1640 string const tmptok = lex.getString();
1641 // check if tmptok is part of tex_graphics in tex_defs.h
1644 string const test = tex_graphics[n++];
1646 if (test == tmptok) {
1647 graphicsDriver = tmptok;
1652 "Warning: graphics driver `$$Token' not recognized!\n"
1653 " Setting graphics driver to `default'.\n");
1654 graphicsDriver = "default";
1661 void BufferParams::readBullets(Lexer & lex)
1666 int const index = lex.getInteger();
1668 int temp_int = lex.getInteger();
1669 user_defined_bullet(index).setFont(temp_int);
1670 temp_bullet(index).setFont(temp_int);
1672 user_defined_bullet(index).setCharacter(temp_int);
1673 temp_bullet(index).setCharacter(temp_int);
1675 user_defined_bullet(index).setSize(temp_int);
1676 temp_bullet(index).setSize(temp_int);
1680 void BufferParams::readBulletsLaTeX(Lexer & lex)
1682 // The bullet class should be able to read this.
1685 int const index = lex.getInteger();
1687 docstring const temp_str = lex.getDocString();
1689 user_defined_bullet(index).setText(temp_str);
1690 temp_bullet(index).setText(temp_str);
1694 void BufferParams::readModules(Lexer & lex)
1696 if (!lex.eatLine()) {
1697 lyxerr << "Error (BufferParams::readModules):"
1698 "Unexpected end of input." << endl;
1702 string mod = lex.getString();
1703 if (mod == "\\end_modules")
1705 addLayoutModule(mod);
1711 void BufferParams::readRemovedModules(Lexer & lex)
1713 if (!lex.eatLine()) {
1714 lyxerr << "Error (BufferParams::readRemovedModules):"
1715 "Unexpected end of input." << endl;
1719 string mod = lex.getString();
1720 if (mod == "\\end_removed_modules")
1722 removedModules_.push_back(mod);
1725 // now we want to remove any removed modules that were previously
1726 // added. normally, that will be because default modules were added in
1727 // setBaseClass(), which gets called when \textclass is read at the
1728 // start of the read.
1729 list<string>::const_iterator rit = removedModules_.begin();
1730 list<string>::const_iterator const ren = removedModules_.end();
1731 for (; rit != ren; rit++) {
1732 LayoutModuleList::iterator const mit = layoutModules_.begin();
1733 LayoutModuleList::iterator const men = layoutModules_.end();
1734 LayoutModuleList::iterator found = find(mit, men, *rit);
1737 layoutModules_.erase(found);
1742 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1744 char real_papersize = papersize;
1745 if (real_papersize == PAPER_DEFAULT)
1746 real_papersize = lyxrc.default_papersize;
1748 switch (real_papersize) {
1750 // could be anything, so don't guess
1752 case PAPER_CUSTOM: {
1753 if (purpose == XDVI && !paperwidth.empty() &&
1754 !paperheight.empty()) {
1755 // heightxwidth<unit>
1756 string first = paperwidth;
1757 string second = paperheight;
1758 if (orientation == ORIENTATION_LANDSCAPE)
1761 return first.erase(first.length() - 2)
1773 // dvips and dvipdfm do not know this
1774 if (purpose == DVIPS || purpose == DVIPDFM)
1778 // dvipdfm does not know this
1779 if (purpose == DVIPDFM)
1783 // dvipdfm does not know this
1784 if (purpose == DVIPDFM)
1787 case PAPER_USEXECUTIVE:
1788 // dvipdfm does not know this
1789 if (purpose == DVIPDFM)
1794 case PAPER_USLETTER:
1796 if (purpose == XDVI)
1803 string const BufferParams::dvips_options() const
1808 && papersize == PAPER_CUSTOM
1809 && !lyxrc.print_paper_dimension_flag.empty()
1810 && !paperwidth.empty()
1811 && !paperheight.empty()) {
1812 // using a custom papersize
1813 result = lyxrc.print_paper_dimension_flag;
1814 result += ' ' + paperwidth;
1815 result += ',' + paperheight;
1817 string const paper_option = paperSizeName(DVIPS);
1818 if (!paper_option.empty() && (paper_option != "letter" ||
1819 orientation != ORIENTATION_LANDSCAPE)) {
1820 // dvips won't accept -t letter -t landscape.
1821 // In all other cases, include the paper size
1823 result = lyxrc.print_paper_flag;
1824 result += ' ' + paper_option;
1827 if (orientation == ORIENTATION_LANDSCAPE &&
1828 papersize != PAPER_CUSTOM)
1829 result += ' ' + lyxrc.print_landscape_flag;
1834 string BufferParams::babelCall(string const & lang_opts) const
1836 string lang_pack = lyxrc.language_package;
1837 if (lang_pack != "\\usepackage{babel}")
1839 // suppress the babel call when there is no babel language defined
1840 // for the document language in the lib/languages file and if no
1841 // other languages are used (lang_opts is then empty)
1842 if (lang_opts.empty())
1844 // If Vietnamese is used, babel must directly be loaded with the
1845 // language options, see
1846 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1847 size_t viet = lang_opts.find("vietnam");
1848 // viet = string::npos when not found
1849 // the same is for all other languages that are not directly supported by
1850 // babel, but where LaTeX-packages add babel support.
1851 // this is currently the case for Latvian, Lithuanian, and Mongolian
1852 size_t latvian = lang_opts.find("latvian");
1853 size_t lithu = lang_opts.find("lithuanian");
1854 size_t mongo = lang_opts.find("mongolian");
1855 // If Japanese is used, babel must directly be loaded with the
1856 // language options, see
1857 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1858 size_t japan = lang_opts.find("japanese");
1859 if (!lyxrc.language_global_options || viet != string::npos
1860 || japan != string::npos || latvian != string::npos
1861 || lithu != string::npos || mongo != string::npos)
1862 return "\\usepackage[" + lang_opts + "]{babel}";
1867 docstring BufferParams::getGraphicsDriver(string const & package) const
1871 if (package == "geometry") {
1872 if (graphicsDriver == "dvips"
1873 || graphicsDriver == "dvipdfm"
1874 || graphicsDriver == "pdftex"
1875 || graphicsDriver == "vtex")
1876 result = from_ascii(graphicsDriver);
1877 else if (graphicsDriver == "dvipdfmx")
1878 result = from_ascii("dvipdfm");
1885 void BufferParams::writeEncodingPreamble(odocstream & os,
1886 LaTeXFeatures & features, TexRow & texrow) const
1890 if (inputenc == "auto") {
1891 string const doc_encoding =
1892 language->encoding()->latexName();
1893 Encoding::Package const package =
1894 language->encoding()->package();
1896 // Create a list with all the input encodings used
1898 set<string> encodings =
1899 features.getEncodingSet(doc_encoding);
1901 // If the "japanese" package (i.e. pLaTeX) is used,
1902 // inputenc must be omitted.
1903 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1904 if (package == Encoding::japanese)
1905 features.require("japanese");
1907 if ((!encodings.empty() || package == Encoding::inputenc)
1908 && !features.isRequired("japanese")) {
1909 os << "\\usepackage[";
1910 set<string>::const_iterator it = encodings.begin();
1911 set<string>::const_iterator const end = encodings.end();
1913 os << from_ascii(*it);
1916 for (; it != end; ++it)
1917 os << ',' << from_ascii(*it);
1918 if (package == Encoding::inputenc) {
1919 if (!encodings.empty())
1921 os << from_ascii(doc_encoding);
1923 os << "]{inputenc}\n";
1926 if (package == Encoding::CJK || features.mustProvide("CJK")) {
1927 if (language->encoding()->name() == "utf8-cjk"
1928 && LaTeXFeatures::isAvailable("CJKutf8"))
1929 os << "\\usepackage{CJKutf8}\n";
1931 os << "\\usepackage{CJK}\n";
1934 } else if (inputenc != "default") {
1935 switch (encoding().package()) {
1936 case Encoding::none:
1937 case Encoding::japanese:
1939 case Encoding::inputenc:
1940 // do not load inputenc if japanese is used
1941 if (features.isRequired("japanese"))
1943 os << "\\usepackage[" << from_ascii(inputenc)
1948 if (encoding().name() == "utf8-cjk"
1949 && LaTeXFeatures::isAvailable("CJKutf8"))
1950 os << "\\usepackage{CJKutf8}\n";
1952 os << "\\usepackage{CJK}\n";
1958 // The encoding "armscii8" (for Armenian) is only available when
1959 // the package "armtex" is loaded.
1960 if (language->encoding()->latexName() == "armscii8"
1961 || inputenc == "armscii8") {
1962 os << "\\usepackage{armtex}\n";
1968 string const BufferParams::parseFontName(string const & name) const
1970 string mangled = name;
1971 size_t const idx = mangled.find('[');
1972 if (idx == string::npos || idx == 0)
1975 return mangled.substr(0, idx - 1);
1979 string const BufferParams::loadFonts(string const & rm,
1980 string const & sf, string const & tt,
1981 bool const & sc, bool const & osf,
1982 int const & sfscale, int const & ttscale,
1983 bool const & xetex) const
1985 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1986 several packages have been replaced by others, that might not
1987 be installed on every system. We have to take care for that
1988 (see psnfss.pdf). We try to support all psnfss fonts as well
1989 as the fonts that have become de facto standard in the LaTeX
1990 world (e.g. Latin Modern). We do not support obsolete fonts
1991 (like PSLatex). In general, it should be possible to mix any
1992 rm font with any sf or tt font, respectively. (JSpitzm)
1994 -- separate math fonts.
1997 if (rm == "default" && sf == "default" && tt == "default")
2004 if (rm != "default")
2005 os << "\\setmainfont[Mapping=tex-text]{"
2006 << parseFontName(rm) << "}\n";
2007 if (sf != "default") {
2008 string const sans = parseFontName(sf);
2010 os << "\\setsansfont[Scale="
2011 << float(sfscale) / 100
2012 << ",Mapping=tex-text]{"
2015 os << "\\setsansfont[Mapping=tex-text]{"
2018 if (tt != "default") {
2019 string const mono = parseFontName(tt);
2021 os << "\\setmonofont[Scale="
2022 << float(sfscale) / 100
2026 os << "\\setmonofont[Mapping=tex-text]{"
2030 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2035 // Computer Modern (must be explicitely selectable -- there might be classes
2036 // that define a different default font!
2038 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2039 // osf for Computer Modern needs eco.sty
2041 os << "\\usepackage{eco}\n";
2043 // Latin Modern Roman
2044 else if (rm == "lmodern")
2045 os << "\\usepackage{lmodern}\n";
2047 else if (rm == "ae") {
2048 // not needed when using OT1 font encoding.
2049 if (lyxrc.fontenc != "default")
2050 os << "\\usepackage{ae,aecompl}\n";
2053 else if (rm == "times") {
2054 // try to load the best available package
2055 if (LaTeXFeatures::isAvailable("mathptmx"))
2056 os << "\\usepackage{mathptmx}\n";
2057 else if (LaTeXFeatures::isAvailable("mathptm"))
2058 os << "\\usepackage{mathptm}\n";
2060 os << "\\usepackage{times}\n";
2063 else if (rm == "palatino") {
2064 // try to load the best available package
2065 if (LaTeXFeatures::isAvailable("mathpazo")) {
2066 os << "\\usepackage";
2072 // "osf" includes "sc"!
2076 os << "{mathpazo}\n";
2078 else if (LaTeXFeatures::isAvailable("mathpple"))
2079 os << "\\usepackage{mathpple}\n";
2081 os << "\\usepackage{palatino}\n";
2084 else if (rm == "utopia") {
2085 // fourier supersedes utopia.sty, but does
2086 // not work with OT1 encoding.
2087 if (LaTeXFeatures::isAvailable("fourier")
2088 && lyxrc.fontenc != "default") {
2089 os << "\\usepackage";
2100 os << "{fourier}\n";
2103 os << "\\usepackage{utopia}\n";
2105 // Bera (complete fontset)
2106 else if (rm == "bera" && sf == "default" && tt == "default")
2107 os << "\\usepackage{bera}\n";
2109 else if (rm != "default")
2110 os << "\\usepackage" << "{" << rm << "}\n";
2113 // Helvetica, Bera Sans
2114 if (sf == "helvet" || sf == "berasans") {
2116 os << "\\usepackage[scaled=" << float(sfscale) / 100
2117 << "]{" << sf << "}\n";
2119 os << "\\usepackage{" << sf << "}\n";
2122 else if (sf == "avant")
2123 os << "\\usepackage{" << sf << "}\n";
2124 // Computer Modern, Latin Modern, CM Bright
2125 else if (sf != "default")
2126 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2128 // monospaced/typewriter
2129 // Courier, LuxiMono
2130 if (tt == "luximono" || tt == "beramono") {
2132 os << "\\usepackage[scaled=" << float(ttscale) / 100
2133 << "]{" << tt << "}\n";
2135 os << "\\usepackage{" << tt << "}\n";
2138 else if (tt == "courier" )
2139 os << "\\usepackage{" << tt << "}\n";
2140 // Computer Modern, Latin Modern, CM Bright
2141 else if (tt != "default")
2142 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2148 Encoding const & BufferParams::encoding() const
2151 return *(encodings.fromLaTeXName("utf8-plain"));
2152 if (inputenc == "auto" || inputenc == "default")
2153 return *language->encoding();
2154 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2157 LYXERR0("Unknown inputenc value `" << inputenc
2158 << "'. Using `auto' instead.");
2159 return *language->encoding();
2163 CiteEngine BufferParams::citeEngine() const
2165 // FIXME the class should provide the numerical/
2166 // authoryear choice
2167 if (documentClass().provides("natbib")
2168 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2169 return ENGINE_NATBIB_AUTHORYEAR;
2170 return cite_engine_;
2174 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2176 cite_engine_ = cite_engine;