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";
1094 // font selection must be done before loading fontenc.sty
1095 string const fonts =
1096 loadFonts(fontsRoman, fontsSans,
1097 fontsTypewriter, fontsSC, fontsOSF,
1098 fontsSansScale, fontsTypewriterScale, useXetex);
1099 if (!fonts.empty()) {
1100 os << from_ascii(fonts);
1103 if (fontsDefaultFamily != "default")
1104 os << "\\renewcommand{\\familydefault}{\\"
1105 << from_ascii(fontsDefaultFamily) << "}\n";
1107 // set font encoding
1108 // this one is not per buffer
1109 // for arabic_arabi and farsi we also need to load the LAE and
1111 // XeteX works without fontenc
1112 if (lyxrc.fontenc != "default" && language->lang() != "japanese"
1114 if (language->lang() == "arabic_arabi"
1115 || language->lang() == "farsi") {
1116 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1117 << ",LFE,LAE]{fontenc}\n";
1120 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1126 // handle inputenc etc.
1127 writeEncodingPreamble(os, features, texrow);
1129 if (!listings_params.empty() || features.isRequired("listings")) {
1130 os << "\\usepackage{listings}\n";
1133 if (!listings_params.empty()) {
1135 // do not test validity because listings_params is
1136 // supposed to be valid
1138 InsetListingsParams(listings_params).separatedParams(true);
1139 // we can't support all packages, but we should load the color package
1140 if (par.find("\\color", 0) != string::npos)
1141 features.require("color");
1142 os << from_utf8(par);
1143 // count the number of newlines
1144 for (size_t i = 0; i < par.size(); ++i)
1150 if (!tclass.provides("geometry")
1151 && (use_geometry || nonstandard_papersize)) {
1152 odocstringstream ods;
1153 if (!getGraphicsDriver("geometry").empty())
1154 ods << getGraphicsDriver("geometry");
1155 if (orientation == ORIENTATION_LANDSCAPE)
1156 ods << ",landscape";
1157 switch (papersize) {
1159 if (!paperwidth.empty())
1160 ods << ",paperwidth="
1161 << from_ascii(paperwidth);
1162 if (!paperheight.empty())
1163 ods << ",paperheight="
1164 << from_ascii(paperheight);
1166 case PAPER_USLETTER:
1167 ods << ",letterpaper";
1170 ods << ",legalpaper";
1172 case PAPER_USEXECUTIVE:
1173 ods << ",executivepaper";
1194 // default papersize ie PAPER_DEFAULT
1195 switch (lyxrc.default_papersize) {
1196 case PAPER_DEFAULT: // keep compiler happy
1197 case PAPER_USLETTER:
1198 ods << ",letterpaper";
1201 ods << ",legalpaper";
1203 case PAPER_USEXECUTIVE:
1204 ods << ",executivepaper";
1224 docstring const g_options = trim(ods.str(), ",");
1225 os << "\\usepackage";
1226 if (!g_options.empty())
1227 os << '[' << g_options << ']';
1228 os << "{geometry}\n";
1230 os << "\\geometry{verbose";
1231 if (!topmargin.empty())
1232 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1233 if (!bottommargin.empty())
1234 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1235 if (!leftmargin.empty())
1236 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1237 if (!rightmargin.empty())
1238 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1239 if (!headheight.empty())
1240 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1241 if (!headsep.empty())
1242 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1243 if (!footskip.empty())
1244 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1245 if (!columnsep.empty())
1246 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1249 } else if (orientation == ORIENTATION_LANDSCAPE) {
1250 features.require("papersize");
1253 if (tokenPos(tclass.opt_pagestyle(),
1254 '|', pagestyle) >= 0) {
1255 if (pagestyle == "fancy") {
1256 os << "\\usepackage{fancyhdr}\n";
1259 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1263 // Only if class has a ToC hierarchy
1264 if (tclass.hasTocLevels()) {
1265 if (secnumdepth != tclass.secnumdepth()) {
1266 os << "\\setcounter{secnumdepth}{"
1271 if (tocdepth != tclass.tocdepth()) {
1272 os << "\\setcounter{tocdepth}{"
1279 if (paragraph_separation) {
1280 switch (getDefSkip().kind()) {
1281 case VSpace::SMALLSKIP:
1282 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1284 case VSpace::MEDSKIP:
1285 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1287 case VSpace::BIGSKIP:
1288 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1290 case VSpace::LENGTH:
1291 os << "\\setlength{\\parskip}{"
1292 << from_utf8(getDefSkip().length().asLatexString())
1295 default: // should never happen // Then delete it.
1296 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1301 os << "\\setlength{\\parindent}{0pt}\n";
1305 // Now insert the LyX specific LaTeX commands...
1306 docstring lyxpreamble;
1308 // due to interferences with babel and hyperref, the color package has to
1309 // be loaded (when it is not already loaded) before babel when hyperref
1310 // is used with the colorlinks option, see
1311 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1312 // we decided therefore to load color always before babel, see
1313 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1314 lyxpreamble += from_ascii(features.getColorOptions());
1316 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1318 && (features.isRequired("jurabib")
1319 || features.isRequired("hyperref")
1320 || features.isRequired("vietnamese")
1321 || features.isRequired("japanese") ) ) {
1323 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1324 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1327 // The optional packages;
1328 lyxpreamble += from_ascii(features.getPackages());
1331 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1334 // * Hyperref manual: "Make sure it comes last of your loaded
1335 // packages, to give it a fighting chance of not being over-written,
1336 // since its job is to redefine many LaTeX commands."
1337 // * Email from Heiko Oberdiek: "It is usually better to load babel
1338 // before hyperref. Then hyperref has a chance to detect babel.
1339 // * Has to be loaded before the "LyX specific LaTeX commands" to
1340 // avoid errors with algorithm floats.
1341 // use hyperref explicitely when it is required
1342 if (features.isRequired("hyperref")) {
1343 odocstringstream oss;
1344 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1345 lyxpreamble += oss.str();
1348 // Will be surrounded by \makeatletter and \makeatother when needed
1349 docstring atlyxpreamble;
1351 // Some macros LyX will need
1352 docstring tmppreamble(from_ascii(features.getMacros()));
1354 if (!tmppreamble.empty())
1355 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1356 "LyX specific LaTeX commands.\n"
1357 + tmppreamble + '\n';
1359 // the text class specific preamble
1360 tmppreamble = features.getTClassPreamble();
1361 if (!tmppreamble.empty())
1362 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1363 "Textclass specific LaTeX commands.\n"
1364 + tmppreamble + '\n';
1366 /* the user-defined preamble */
1367 if (!preamble.empty())
1369 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1370 "User specified LaTeX commands.\n"
1371 + from_utf8(preamble) + '\n';
1373 // subfig loads internally the LaTeX package "caption". As
1374 // caption is a very popular package, users will load it in
1375 // the preamble. Therefore we must load subfig behind the
1376 // user-defined preamble and check if the caption package was
1377 // loaded or not. For the case that caption is loaded before
1378 // subfig, there is the subfig option "caption=false". This
1379 // option also works when a koma-script class is used and
1380 // koma's own caption commands are used instead of caption. We
1381 // use \PassOptionsToPackage here because the user could have
1382 // already loaded subfig in the preamble.
1383 if (features.isRequired("subfig")) {
1384 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1385 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1386 "\\usepackage{subfig}\n";
1389 // Itemize bullet settings need to be last in case the user
1390 // defines their own bullets that use a package included
1391 // in the user-defined preamble -- ARRae
1392 // Actually it has to be done much later than that
1393 // since some packages like frenchb make modifications
1394 // at \begin{document} time -- JMarc
1395 docstring bullets_def;
1396 for (int i = 0; i < 4; ++i) {
1397 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1398 if (bullets_def.empty())
1399 bullets_def += "\\AtBeginDocument{\n";
1400 bullets_def += " \\def\\labelitemi";
1402 // `i' is one less than the item to modify
1409 bullets_def += "ii";
1415 bullets_def += '{' +
1416 user_defined_bullet(i).getText()
1421 if (!bullets_def.empty())
1422 atlyxpreamble += bullets_def + "}\n\n";
1424 if (atlyxpreamble.find(from_ascii("@")) != docstring::npos)
1425 lyxpreamble += "\n\\makeatletter\n"
1426 + atlyxpreamble + "\\makeatother\n\n";
1428 lyxpreamble += '\n' + atlyxpreamble;
1430 // We try to load babel late, in case it interferes with other packages.
1431 // Jurabib and Hyperref have to be called after babel, though.
1432 if (use_babel && !features.isRequired("jurabib")
1433 && !features.isRequired("hyperref")
1434 && !features.isRequired("vietnamese")
1435 && !features.isRequired("japanese")) {
1437 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1438 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1441 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1442 if (!i18npreamble.empty())
1443 lyxpreamble += i18npreamble + '\n';
1446 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1447 for (int j = 0; j != nlines; ++j) {
1453 // these packages (xunicode, for that matter) need to be loaded at least
1454 // after amsmath, amssymb, esint and the other packages that provide
1457 os << "\\usepackage{xunicode}\n";
1459 os << "\\usepackage{xltxtra}\n";
1466 void BufferParams::useClassDefaults()
1468 DocumentClass const & tclass = documentClass();
1470 sides = tclass.sides();
1471 columns = tclass.columns();
1472 pagestyle = tclass.pagestyle();
1473 use_default_options = true;
1474 // Only if class has a ToC hierarchy
1475 if (tclass.hasTocLevels()) {
1476 secnumdepth = tclass.secnumdepth();
1477 tocdepth = tclass.tocdepth();
1482 bool BufferParams::hasClassDefaults() const
1484 DocumentClass const & tclass = documentClass();
1486 return sides == tclass.sides()
1487 && columns == tclass.columns()
1488 && pagestyle == tclass.pagestyle()
1489 && use_default_options
1490 && secnumdepth == tclass.secnumdepth()
1491 && tocdepth == tclass.tocdepth();
1495 DocumentClass const & BufferParams::documentClass() const
1501 DocumentClass const * BufferParams::documentClassPtr() const {
1506 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1507 // evil, but this function is evil
1508 doc_class_ = const_cast<DocumentClass *>(tc);
1512 bool BufferParams::setBaseClass(string const & classname)
1514 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1515 LayoutFileList & bcl = LayoutFileList::get();
1516 if (!bcl.haveClass(classname)) {
1518 bformat(_("The document class %1$s could not be found. "
1519 "A default textclass with default layouts will be used. "
1520 "LyX might not be able to produce output unless a correct "
1521 "textclass is selected from the document settings dialog."),
1522 from_utf8(classname));
1523 frontend::Alert::error(_("Document class not found"), s);
1524 bcl.addEmptyClass(classname);
1527 bool const success = bcl[classname].load();
1530 bformat(_("The document class %1$s could not be loaded."),
1531 from_utf8(classname));
1532 frontend::Alert::error(_("Could not load class"), s);
1536 pimpl_->baseClass_ = classname;
1537 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1542 LayoutFile const * BufferParams::baseClass() const
1544 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1545 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1551 LayoutFileIndex const & BufferParams::baseClassID() const
1553 return pimpl_->baseClass_;
1557 void BufferParams::makeDocumentClass()
1562 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1564 if (!local_layout.empty()) {
1565 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1566 docstring const msg = _("Error reading internal layout information");
1567 frontend::Alert::warning(_("Read Error"), msg);
1572 bool BufferParams::moduleCanBeAdded(string const & modName) const
1574 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1578 bool BufferParams::addLayoutModule(string const & modName)
1580 LayoutModuleList::const_iterator it = layoutModules_.begin();
1581 LayoutModuleList::const_iterator end = layoutModules_.end();
1582 for (; it != end; it++)
1585 layoutModules_.push_back(modName);
1590 Font const BufferParams::getFont() const
1592 FontInfo f = documentClass().defaultfont();
1593 if (fontsDefaultFamily == "rmdefault")
1594 f.setFamily(ROMAN_FAMILY);
1595 else if (fontsDefaultFamily == "sfdefault")
1596 f.setFamily(SANS_FAMILY);
1597 else if (fontsDefaultFamily == "ttdefault")
1598 f.setFamily(TYPEWRITER_FAMILY);
1599 return Font(f, language);
1603 void BufferParams::readPreamble(Lexer & lex)
1605 if (lex.getString() != "\\begin_preamble")
1606 lyxerr << "Error (BufferParams::readPreamble):"
1607 "consistency check failed." << endl;
1609 preamble = lex.getLongString("\\end_preamble");
1613 void BufferParams::readLocalLayout(Lexer & lex)
1615 if (lex.getString() != "\\begin_local_layout")
1616 lyxerr << "Error (BufferParams::readLocalLayout):"
1617 "consistency check failed." << endl;
1619 local_layout = lex.getLongString("\\end_local_layout");
1623 void BufferParams::readLanguage(Lexer & lex)
1625 if (!lex.next()) return;
1627 string const tmptok = lex.getString();
1629 // check if tmptok is part of tex_babel in tex-defs.h
1630 language = languages.getLanguage(tmptok);
1632 // Language tmptok was not found
1633 language = default_language;
1634 lyxerr << "Warning: Setting language `"
1635 << tmptok << "' to `" << language->lang()
1641 void BufferParams::readGraphicsDriver(Lexer & lex)
1646 string const tmptok = lex.getString();
1647 // check if tmptok is part of tex_graphics in tex_defs.h
1650 string const test = tex_graphics[n++];
1652 if (test == tmptok) {
1653 graphicsDriver = tmptok;
1658 "Warning: graphics driver `$$Token' not recognized!\n"
1659 " Setting graphics driver to `default'.\n");
1660 graphicsDriver = "default";
1667 void BufferParams::readBullets(Lexer & lex)
1672 int const index = lex.getInteger();
1674 int temp_int = lex.getInteger();
1675 user_defined_bullet(index).setFont(temp_int);
1676 temp_bullet(index).setFont(temp_int);
1678 user_defined_bullet(index).setCharacter(temp_int);
1679 temp_bullet(index).setCharacter(temp_int);
1681 user_defined_bullet(index).setSize(temp_int);
1682 temp_bullet(index).setSize(temp_int);
1686 void BufferParams::readBulletsLaTeX(Lexer & lex)
1688 // The bullet class should be able to read this.
1691 int const index = lex.getInteger();
1693 docstring const temp_str = lex.getDocString();
1695 user_defined_bullet(index).setText(temp_str);
1696 temp_bullet(index).setText(temp_str);
1700 void BufferParams::readModules(Lexer & lex)
1702 if (!lex.eatLine()) {
1703 lyxerr << "Error (BufferParams::readModules):"
1704 "Unexpected end of input." << endl;
1708 string mod = lex.getString();
1709 if (mod == "\\end_modules")
1711 addLayoutModule(mod);
1717 void BufferParams::readRemovedModules(Lexer & lex)
1719 if (!lex.eatLine()) {
1720 lyxerr << "Error (BufferParams::readRemovedModules):"
1721 "Unexpected end of input." << endl;
1725 string mod = lex.getString();
1726 if (mod == "\\end_removed_modules")
1728 removedModules_.push_back(mod);
1731 // now we want to remove any removed modules that were previously
1732 // added. normally, that will be because default modules were added in
1733 // setBaseClass(), which gets called when \textclass is read at the
1734 // start of the read.
1735 list<string>::const_iterator rit = removedModules_.begin();
1736 list<string>::const_iterator const ren = removedModules_.end();
1737 for (; rit != ren; rit++) {
1738 LayoutModuleList::iterator const mit = layoutModules_.begin();
1739 LayoutModuleList::iterator const men = layoutModules_.end();
1740 LayoutModuleList::iterator found = find(mit, men, *rit);
1743 layoutModules_.erase(found);
1748 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1750 char real_papersize = papersize;
1751 if (real_papersize == PAPER_DEFAULT)
1752 real_papersize = lyxrc.default_papersize;
1754 switch (real_papersize) {
1756 // could be anything, so don't guess
1758 case PAPER_CUSTOM: {
1759 if (purpose == XDVI && !paperwidth.empty() &&
1760 !paperheight.empty()) {
1761 // heightxwidth<unit>
1762 string first = paperwidth;
1763 string second = paperheight;
1764 if (orientation == ORIENTATION_LANDSCAPE)
1767 return first.erase(first.length() - 2)
1779 // dvips and dvipdfm do not know this
1780 if (purpose == DVIPS || purpose == DVIPDFM)
1784 // dvipdfm does not know this
1785 if (purpose == DVIPDFM)
1789 // dvipdfm does not know this
1790 if (purpose == DVIPDFM)
1793 case PAPER_USEXECUTIVE:
1794 // dvipdfm does not know this
1795 if (purpose == DVIPDFM)
1800 case PAPER_USLETTER:
1802 if (purpose == XDVI)
1809 string const BufferParams::dvips_options() const
1814 && papersize == PAPER_CUSTOM
1815 && !lyxrc.print_paper_dimension_flag.empty()
1816 && !paperwidth.empty()
1817 && !paperheight.empty()) {
1818 // using a custom papersize
1819 result = lyxrc.print_paper_dimension_flag;
1820 result += ' ' + paperwidth;
1821 result += ',' + paperheight;
1823 string const paper_option = paperSizeName(DVIPS);
1824 if (!paper_option.empty() && (paper_option != "letter" ||
1825 orientation != ORIENTATION_LANDSCAPE)) {
1826 // dvips won't accept -t letter -t landscape.
1827 // In all other cases, include the paper size
1829 result = lyxrc.print_paper_flag;
1830 result += ' ' + paper_option;
1833 if (orientation == ORIENTATION_LANDSCAPE &&
1834 papersize != PAPER_CUSTOM)
1835 result += ' ' + lyxrc.print_landscape_flag;
1840 string BufferParams::babelCall(string const & lang_opts) const
1842 string lang_pack = lyxrc.language_package;
1843 if (lang_pack != "\\usepackage{babel}")
1845 // suppress the babel call when there is no babel language defined
1846 // for the document language in the lib/languages file and if no
1847 // other languages are used (lang_opts is then empty)
1848 if (lang_opts.empty())
1850 // If Vietnamese is used, babel must directly be loaded with the
1851 // language options, see
1852 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1853 size_t viet = lang_opts.find("vietnam");
1854 // viet = string::npos when not found
1855 // the same is for all other languages that are not directly supported by
1856 // babel, but where LaTeX-packages add babel support.
1857 // this is currently the case for Latvian, Lithuanian, and Mongolian
1858 size_t latvian = lang_opts.find("latvian");
1859 size_t lithu = lang_opts.find("lithuanian");
1860 size_t mongo = lang_opts.find("mongolian");
1861 // If Japanese is used, babel must directly be loaded with the
1862 // language options, see
1863 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1864 size_t japan = lang_opts.find("japanese");
1865 if (!lyxrc.language_global_options || viet != string::npos
1866 || japan != string::npos || latvian != string::npos
1867 || lithu != string::npos || mongo != string::npos)
1868 return "\\usepackage[" + lang_opts + "]{babel}";
1873 docstring BufferParams::getGraphicsDriver(string const & package) const
1877 if (package == "geometry") {
1878 if (graphicsDriver == "dvips"
1879 || graphicsDriver == "dvipdfm"
1880 || graphicsDriver == "pdftex"
1881 || graphicsDriver == "vtex")
1882 result = from_ascii(graphicsDriver);
1883 else if (graphicsDriver == "dvipdfmx")
1884 result = from_ascii("dvipdfm");
1891 void BufferParams::writeEncodingPreamble(odocstream & os,
1892 LaTeXFeatures & features, TexRow & texrow) const
1896 if (inputenc == "auto") {
1897 string const doc_encoding =
1898 language->encoding()->latexName();
1899 Encoding::Package const package =
1900 language->encoding()->package();
1902 // Create a list with all the input encodings used
1904 set<string> encodings =
1905 features.getEncodingSet(doc_encoding);
1907 // If the "japanese" package (i.e. pLaTeX) is used,
1908 // inputenc must be omitted.
1909 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1910 if (package == Encoding::japanese)
1911 features.require("japanese");
1913 if ((!encodings.empty() || package == Encoding::inputenc)
1914 && !features.isRequired("japanese")) {
1915 os << "\\usepackage[";
1916 set<string>::const_iterator it = encodings.begin();
1917 set<string>::const_iterator const end = encodings.end();
1919 os << from_ascii(*it);
1922 for (; it != end; ++it)
1923 os << ',' << from_ascii(*it);
1924 if (package == Encoding::inputenc) {
1925 if (!encodings.empty())
1927 os << from_ascii(doc_encoding);
1929 os << "]{inputenc}\n";
1932 if (package == Encoding::CJK || features.mustProvide("CJK")) {
1933 if (language->encoding()->name() == "utf8-cjk"
1934 && LaTeXFeatures::isAvailable("CJKutf8"))
1935 os << "\\usepackage{CJKutf8}\n";
1937 os << "\\usepackage{CJK}\n";
1940 } else if (inputenc != "default") {
1941 switch (encoding().package()) {
1942 case Encoding::none:
1943 case Encoding::japanese:
1945 case Encoding::inputenc:
1946 // do not load inputenc if japanese is used
1947 if (features.isRequired("japanese"))
1949 os << "\\usepackage[" << from_ascii(inputenc)
1954 if (encoding().name() == "utf8-cjk"
1955 && LaTeXFeatures::isAvailable("CJKutf8"))
1956 os << "\\usepackage{CJKutf8}\n";
1958 os << "\\usepackage{CJK}\n";
1964 // The encoding "armscii8" (for Armenian) is only available when
1965 // the package "armtex" is loaded.
1966 if (language->encoding()->latexName() == "armscii8"
1967 || inputenc == "armscii8") {
1968 os << "\\usepackage{armtex}\n";
1974 string const BufferParams::parseFontName(string const & name) const
1976 string mangled = name;
1977 size_t const idx = mangled.find('[');
1978 if (idx == string::npos || idx == 0)
1981 return mangled.substr(0, idx - 1);
1985 string const BufferParams::loadFonts(string const & rm,
1986 string const & sf, string const & tt,
1987 bool const & sc, bool const & osf,
1988 int const & sfscale, int const & ttscale,
1989 bool const & xetex) const
1991 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1992 several packages have been replaced by others, that might not
1993 be installed on every system. We have to take care for that
1994 (see psnfss.pdf). We try to support all psnfss fonts as well
1995 as the fonts that have become de facto standard in the LaTeX
1996 world (e.g. Latin Modern). We do not support obsolete fonts
1997 (like PSLatex). In general, it should be possible to mix any
1998 rm font with any sf or tt font, respectively. (JSpitzm)
2000 -- separate math fonts.
2003 if (rm == "default" && sf == "default" && tt == "default")
2010 if (rm != "default")
2011 os << "\\setmainfont[Mapping=tex-text]{"
2012 << parseFontName(rm) << "}\n";
2013 if (sf != "default") {
2014 string const sans = parseFontName(sf);
2016 os << "\\setsansfont[Scale="
2017 << float(sfscale) / 100
2018 << ",Mapping=tex-text]{"
2021 os << "\\setsansfont[Mapping=tex-text]{"
2024 if (tt != "default") {
2025 string const mono = parseFontName(tt);
2027 os << "\\setmonofont[Scale="
2028 << float(sfscale) / 100
2032 os << "\\setmonofont[Mapping=tex-text]{"
2036 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2041 // Computer Modern (must be explicitely selectable -- there might be classes
2042 // that define a different default font!
2044 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2045 // osf for Computer Modern needs eco.sty
2047 os << "\\usepackage{eco}\n";
2049 // Latin Modern Roman
2050 else if (rm == "lmodern")
2051 os << "\\usepackage{lmodern}\n";
2053 else if (rm == "ae") {
2054 // not needed when using OT1 font encoding.
2055 if (lyxrc.fontenc != "default")
2056 os << "\\usepackage{ae,aecompl}\n";
2059 else if (rm == "times") {
2060 // try to load the best available package
2061 if (LaTeXFeatures::isAvailable("mathptmx"))
2062 os << "\\usepackage{mathptmx}\n";
2063 else if (LaTeXFeatures::isAvailable("mathptm"))
2064 os << "\\usepackage{mathptm}\n";
2066 os << "\\usepackage{times}\n";
2069 else if (rm == "palatino") {
2070 // try to load the best available package
2071 if (LaTeXFeatures::isAvailable("mathpazo")) {
2072 os << "\\usepackage";
2078 // "osf" includes "sc"!
2082 os << "{mathpazo}\n";
2084 else if (LaTeXFeatures::isAvailable("mathpple"))
2085 os << "\\usepackage{mathpple}\n";
2087 os << "\\usepackage{palatino}\n";
2090 else if (rm == "utopia") {
2091 // fourier supersedes utopia.sty, but does
2092 // not work with OT1 encoding.
2093 if (LaTeXFeatures::isAvailable("fourier")
2094 && lyxrc.fontenc != "default") {
2095 os << "\\usepackage";
2106 os << "{fourier}\n";
2109 os << "\\usepackage{utopia}\n";
2111 // Bera (complete fontset)
2112 else if (rm == "bera" && sf == "default" && tt == "default")
2113 os << "\\usepackage{bera}\n";
2115 else if (rm != "default")
2116 os << "\\usepackage" << "{" << rm << "}\n";
2119 // Helvetica, Bera Sans
2120 if (sf == "helvet" || sf == "berasans") {
2122 os << "\\usepackage[scaled=" << float(sfscale) / 100
2123 << "]{" << sf << "}\n";
2125 os << "\\usepackage{" << sf << "}\n";
2128 else if (sf == "avant")
2129 os << "\\usepackage{" << sf << "}\n";
2130 // Computer Modern, Latin Modern, CM Bright
2131 else if (sf != "default")
2132 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2134 // monospaced/typewriter
2135 // Courier, LuxiMono
2136 if (tt == "luximono" || tt == "beramono") {
2138 os << "\\usepackage[scaled=" << float(ttscale) / 100
2139 << "]{" << tt << "}\n";
2141 os << "\\usepackage{" << tt << "}\n";
2144 else if (tt == "courier" )
2145 os << "\\usepackage{" << tt << "}\n";
2146 // Computer Modern, Latin Modern, CM Bright
2147 else if (tt != "default")
2148 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2154 Encoding const & BufferParams::encoding() const
2157 return *(encodings.fromLaTeXName("utf8-plain"));
2158 if (inputenc == "auto" || inputenc == "default")
2159 return *language->encoding();
2160 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2163 LYXERR0("Unknown inputenc value `" << inputenc
2164 << "'. Using `auto' instead.");
2165 return *language->encoding();
2169 CiteEngine BufferParams::citeEngine() const
2171 // FIXME the class should provide the numerical/
2172 // authoryear choice
2173 if (documentClass().provides("natbib")
2174 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2175 return ENGINE_NATBIB_AUTHORYEAR;
2176 return cite_engine_;
2180 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2182 cite_engine_ = cite_engine;