2 * \file BufferParams.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alfredo Braunstein
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
11 * \author Martin Vermeer
13 * Full author contact details are available in file CREDITS.
18 #include "BufferParams.h"
21 #include "LayoutFile.h"
22 #include "BranchList.h"
23 #include "buffer_funcs.h"
28 #include "LaTeXFeatures.h"
29 #include "ModuleList.h"
33 #include "OutputParams.h"
37 #include "PDFOptions.h"
39 #include "frontends/alert.h"
41 #include "insets/InsetListingsParams.h"
43 #include "support/convert.h"
44 #include "support/debug.h"
45 #include "support/docstream.h"
46 #include "support/FileName.h"
47 #include "support/filetools.h"
48 #include "support/gettext.h"
49 #include "support/Messages.h"
50 #include "support/Translator.h"
51 #include "support/lstrings.h"
57 using namespace lyx::support;
60 static char const * const string_paragraph_separation[] = {
65 static char const * const string_quotes_language[] = {
66 "english", "swedish", "german", "polish", "french", "danish", ""
70 static char const * const string_papersize[] = {
71 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
72 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
76 static char const * const string_orientation[] = {
77 "portrait", "landscape", ""
81 static char const * const string_footnotekinds[] = {
82 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
86 static char const * const tex_graphics[] = {
87 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
88 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
89 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
90 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
100 // Paragraph separation
101 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
104 ParSepTranslator const init_parseptranslator()
106 ParSepTranslator translator
107 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
108 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
113 ParSepTranslator const & parseptranslator()
115 static ParSepTranslator translator = init_parseptranslator();
121 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
124 QuotesLangTranslator const init_quoteslangtranslator()
126 QuotesLangTranslator translator
127 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
128 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
129 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
130 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
131 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
132 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
137 QuotesLangTranslator const & quoteslangtranslator()
139 static QuotesLangTranslator translator = init_quoteslangtranslator();
145 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
148 static PaperSizeTranslator initPaperSizeTranslator()
150 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
151 translator.addPair(string_papersize[1], PAPER_CUSTOM);
152 translator.addPair(string_papersize[2], PAPER_USLETTER);
153 translator.addPair(string_papersize[3], PAPER_USLEGAL);
154 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
155 translator.addPair(string_papersize[5], PAPER_A3);
156 translator.addPair(string_papersize[6], PAPER_A4);
157 translator.addPair(string_papersize[7], PAPER_A5);
158 translator.addPair(string_papersize[8], PAPER_B3);
159 translator.addPair(string_papersize[9], PAPER_B4);
160 translator.addPair(string_papersize[10], PAPER_B5);
165 PaperSizeTranslator const & papersizetranslator()
167 static PaperSizeTranslator translator = initPaperSizeTranslator();
173 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
176 PaperOrientationTranslator const init_paperorientationtranslator()
178 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
179 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
184 PaperOrientationTranslator const & paperorientationtranslator()
186 static PaperOrientationTranslator translator = init_paperorientationtranslator();
192 typedef Translator<int, PageSides> SidesTranslator;
195 SidesTranslator const init_sidestranslator()
197 SidesTranslator translator(1, OneSide);
198 translator.addPair(2, TwoSides);
203 SidesTranslator const & sidestranslator()
205 static SidesTranslator translator = init_sidestranslator();
211 typedef Translator<int, BufferParams::Package> PackageTranslator;
214 PackageTranslator const init_packagetranslator()
216 PackageTranslator translator(0, BufferParams::package_off);
217 translator.addPair(1, BufferParams::package_auto);
218 translator.addPair(2, BufferParams::package_on);
223 PackageTranslator const & packagetranslator()
225 static PackageTranslator translator = init_packagetranslator();
231 typedef Translator<string, CiteEngine> CiteEngineTranslator;
234 CiteEngineTranslator const init_citeenginetranslator()
236 CiteEngineTranslator translator("basic", ENGINE_BASIC);
237 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
238 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
239 translator.addPair("jurabib", ENGINE_JURABIB);
244 CiteEngineTranslator const & citeenginetranslator()
246 static CiteEngineTranslator translator = init_citeenginetranslator();
252 typedef Translator<string, Spacing::Space> SpaceTranslator;
255 SpaceTranslator const init_spacetranslator()
257 SpaceTranslator translator("default", Spacing::Default);
258 translator.addPair("single", Spacing::Single);
259 translator.addPair("onehalf", Spacing::Onehalf);
260 translator.addPair("double", Spacing::Double);
261 translator.addPair("other", Spacing::Other);
266 SpaceTranslator const & spacetranslator()
268 static SpaceTranslator translator = init_spacetranslator();
276 class BufferParams::Impl
281 AuthorList authorlist;
282 BranchList branchlist;
283 Bullet temp_bullets[4];
284 Bullet user_defined_bullets[4];
286 /** This is the amount of space used for paragraph_separation "skip",
287 * and for detached paragraphs in "indented" documents.
290 PDFOptions pdfoptions;
291 LayoutFileIndex baseClass_;
295 BufferParams::Impl::Impl()
296 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
298 // set initial author
300 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
305 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
309 return new BufferParams::Impl(*ptr);
313 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
319 BufferParams::BufferParams()
322 setBaseClass(defaultBaseclass());
324 paragraph_separation = ParagraphIndentSeparation;
325 quotes_language = InsetQuotes::EnglishQuotes;
326 fontsize = "default";
329 papersize = PAPER_DEFAULT;
330 orientation = ORIENTATION_PORTRAIT;
331 use_geometry = false;
332 use_amsmath = package_auto;
333 use_esint = package_auto;
334 cite_engine_ = ENGINE_BASIC;
335 use_bibtopic = false;
336 trackChanges = false;
337 outputChanges = false;
340 language = default_language;
341 fontsRoman = "default";
342 fontsSans = "default";
343 fontsTypewriter = "default";
344 fontsDefaultFamily = "default";
347 fontsSansScale = 100;
348 fontsTypewriterScale = 100;
350 graphicsDriver = "default";
353 listings_params = string();
354 pagestyle = "default";
356 for (int iter = 0; iter < 4; ++iter) {
357 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
358 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
363 docstring BufferParams::B_(string const & l10n) const
365 LASSERT(language, /**/);
366 return getMessages(language->code()).get(l10n);
370 AuthorList & BufferParams::authors()
372 return pimpl_->authorlist;
376 AuthorList const & BufferParams::authors() const
378 return pimpl_->authorlist;
382 BranchList & BufferParams::branchlist()
384 return pimpl_->branchlist;
388 BranchList const & BufferParams::branchlist() const
390 return pimpl_->branchlist;
394 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
396 LASSERT(index < 4, /**/);
397 return pimpl_->temp_bullets[index];
401 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
403 LASSERT(index < 4, /**/);
404 return pimpl_->temp_bullets[index];
408 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
410 LASSERT(index < 4, /**/);
411 return pimpl_->user_defined_bullets[index];
415 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
417 LASSERT(index < 4, /**/);
418 return pimpl_->user_defined_bullets[index];
422 Spacing & BufferParams::spacing()
424 return pimpl_->spacing;
428 Spacing const & BufferParams::spacing() const
430 return pimpl_->spacing;
434 PDFOptions & BufferParams::pdfoptions()
436 return pimpl_->pdfoptions;
440 PDFOptions const & BufferParams::pdfoptions() const
442 return pimpl_->pdfoptions;
446 VSpace const & BufferParams::getDefSkip() const
448 return pimpl_->defskip;
452 void BufferParams::setDefSkip(VSpace const & vs)
454 pimpl_->defskip = vs;
458 string BufferParams::readToken(Lexer & lex, string const & token,
459 FileName const & filepath)
461 if (token == "\\textclass") {
463 string const classname = lex.getString();
464 // if there exists a local layout file, ignore the system one
465 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
467 LayoutFileList & bcl = LayoutFileList::get();
468 if (tcp.empty() && !filepath.empty())
469 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
473 setBaseClass(classname);
474 // We assume that a tex class exists for local or unknown layouts so this warning
475 // will only be given for system layouts.
476 if (!baseClass()->isTeXClassAvailable()) {
477 docstring const msg =
478 bformat(_("The layout file requested by this document,\n"
480 "is not usable. This is probably because a LaTeX\n"
481 "class or style file required by it is not\n"
482 "available. See the Customization documentation\n"
483 "for more information.\n"), from_utf8(classname));
484 frontend::Alert::warning(_("Document class not available"),
485 msg + _("LyX will not be able to produce output."));
487 } else if (token == "\\begin_preamble") {
489 } else if (token == "\\begin_local_layout") {
490 readLocalLayout(lex);
491 } else if (token == "\\begin_modules") {
493 } else if (token == "\\begin_removed_modules") {
494 readRemovedModules(lex);
495 } else if (token == "\\options") {
497 options = lex.getString();
498 } else if (token == "\\master") {
500 master = lex.getString();
501 } else if (token == "\\language") {
503 } else if (token == "\\inputencoding") {
505 } else if (token == "\\graphics") {
506 readGraphicsDriver(lex);
507 } else if (token == "\\font_roman") {
509 } else if (token == "\\font_sans") {
511 } else if (token == "\\font_typewriter") {
512 lex >> fontsTypewriter;
513 } else if (token == "\\font_default_family") {
514 lex >> fontsDefaultFamily;
515 } else if (token == "\\font_sc") {
517 } else if (token == "\\font_osf") {
519 } else if (token == "\\font_sf_scale") {
520 lex >> fontsSansScale;
521 } else if (token == "\\font_tt_scale") {
522 lex >> fontsTypewriterScale;
523 } else if (token == "\\font_cjk") {
525 } else if (token == "\\paragraph_separation") {
528 paragraph_separation = parseptranslator().find(parsep);
529 } else if (token == "\\defskip") {
531 string defskip = lex.getString();
532 if (defskip == "defskip")
535 pimpl_->defskip = VSpace(defskip);
536 } else if (token == "\\quotes_language") {
539 quotes_language = quoteslangtranslator().find(quotes_lang);
540 } else if (token == "\\papersize") {
543 papersize = papersizetranslator().find(ppsize);
544 } else if (token == "\\use_geometry") {
546 } else if (token == "\\use_amsmath") {
549 use_amsmath = packagetranslator().find(use_ams);
550 } else if (token == "\\use_esint") {
553 use_esint = packagetranslator().find(useesint);
554 } else if (token == "\\cite_engine") {
557 cite_engine_ = citeenginetranslator().find(engine);
558 } else if (token == "\\use_bibtopic") {
560 } else if (token == "\\tracking_changes") {
562 } else if (token == "\\output_changes") {
563 lex >> outputChanges;
564 } else if (token == "\\branch") {
566 docstring branch = lex.getDocString();
567 branchlist().add(branch);
570 string const tok = lex.getString();
571 if (tok == "\\end_branch")
573 Branch * branch_ptr = branchlist().find(branch);
574 if (tok == "\\selected") {
577 branch_ptr->setSelected(lex.getInteger());
579 // not yet operational
580 if (tok == "\\color") {
582 string color = lex.getString();
584 branch_ptr->setColor(color);
585 // Update also the Color table:
587 color = lcolor.getX11Name(Color_background);
589 lcolor.setColor(to_utf8(branch), color);
593 } else if (token == "\\author") {
595 istringstream ss(lex.getString());
598 author_map.push_back(pimpl_->authorlist.record(a));
599 } else if (token == "\\paperorientation") {
602 orientation = paperorientationtranslator().find(orient);
603 } else if (token == "\\paperwidth") {
605 } else if (token == "\\paperheight") {
607 } else if (token == "\\leftmargin") {
609 } else if (token == "\\topmargin") {
611 } else if (token == "\\rightmargin") {
613 } else if (token == "\\bottommargin") {
615 } else if (token == "\\headheight") {
617 } else if (token == "\\headsep") {
619 } else if (token == "\\footskip") {
621 } else if (token == "\\columnsep") {
623 } else if (token == "\\paperfontsize") {
625 } else if (token == "\\papercolumns") {
627 } else if (token == "\\listings_params") {
630 listings_params = InsetListingsParams(par).params();
631 } else if (token == "\\papersides") {
634 sides = sidestranslator().find(psides);
635 } else if (token == "\\paperpagestyle") {
637 } else if (token == "\\bullet") {
639 } else if (token == "\\bulletLaTeX") {
640 readBulletsLaTeX(lex);
641 } else if (token == "\\secnumdepth") {
643 } else if (token == "\\tocdepth") {
645 } else if (token == "\\spacing") {
649 if (nspacing == "other") {
652 spacing().set(spacetranslator().find(nspacing), tmp_val);
653 } else if (token == "\\float_placement") {
654 lex >> float_placement;
656 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
657 string toktmp = pdfoptions().readToken(lex, token);
658 if (!toktmp.empty()) {
659 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
664 lyxerr << "BufferParams::readToken(): Unknown token: " <<
673 void BufferParams::writeFile(ostream & os) const
675 // The top of the file is written by the buffer.
676 // Prints out the buffer info into the .lyx file given by file
679 os << "\\textclass " << baseClass()->name() << '\n';
682 if (!preamble.empty()) {
683 // remove '\n' from the end of preamble
684 string const tmppreamble = rtrim(preamble, "\n");
685 os << "\\begin_preamble\n"
687 << "\n\\end_preamble\n";
691 if (!options.empty()) {
692 os << "\\options " << options << '\n';
695 // the master document
696 if (!master.empty()) {
697 os << "\\master " << master << '\n';
701 if (!removedModules_.empty()) {
702 os << "\\begin_removed_modules" << '\n';
703 set<string>::const_iterator it = removedModules_.begin();
704 set<string>::const_iterator en = removedModules_.end();
705 for (; it != en; it++)
707 os << "\\end_removed_modules" << '\n';
711 if (!layoutModules_.empty()) {
712 os << "\\begin_modules" << '\n';
713 LayoutModuleList::const_iterator it = layoutModules_.begin();
714 LayoutModuleList::const_iterator en = layoutModules_.end();
715 for (; it != en; it++)
717 os << "\\end_modules" << '\n';
720 // local layout information
721 if (!local_layout.empty()) {
722 // remove '\n' from the end
723 string const tmplocal = rtrim(local_layout, "\n");
724 os << "\\begin_local_layout\n"
726 << "\n\\end_local_layout\n";
729 // then the text parameters
730 if (language != ignore_language)
731 os << "\\language " << language->lang() << '\n';
732 os << "\\inputencoding " << inputenc
733 << "\n\\font_roman " << fontsRoman
734 << "\n\\font_sans " << fontsSans
735 << "\n\\font_typewriter " << fontsTypewriter
736 << "\n\\font_default_family " << fontsDefaultFamily
737 << "\n\\font_sc " << convert<string>(fontsSC)
738 << "\n\\font_osf " << convert<string>(fontsOSF)
739 << "\n\\font_sf_scale " << fontsSansScale
740 << "\n\\font_tt_scale " << fontsTypewriterScale
742 if (!fontsCJK.empty()) {
743 os << "\\font_cjk " << fontsCJK << '\n';
745 os << "\n\\graphics " << graphicsDriver << '\n';
747 if (!float_placement.empty()) {
748 os << "\\float_placement " << float_placement << '\n';
750 os << "\\paperfontsize " << fontsize << '\n';
752 spacing().writeFile(os);
753 pdfoptions().writeFile(os);
755 os << "\\papersize " << string_papersize[papersize]
756 << "\n\\use_geometry " << convert<string>(use_geometry)
757 << "\n\\use_amsmath " << use_amsmath
758 << "\n\\use_esint " << use_esint
759 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
760 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
761 << "\n\\paperorientation " << string_orientation[orientation]
764 BranchList::const_iterator it = branchlist().begin();
765 BranchList::const_iterator end = branchlist().end();
766 for (; it != end; ++it) {
767 os << "\\branch " << to_utf8(it->branch())
768 << "\n\\selected " << it->isSelected()
769 << "\n\\color " << lyx::X11hexname(it->color())
774 if (!paperwidth.empty())
775 os << "\\paperwidth "
776 << VSpace(paperwidth).asLyXCommand() << '\n';
777 if (!paperheight.empty())
778 os << "\\paperheight "
779 << VSpace(paperheight).asLyXCommand() << '\n';
780 if (!leftmargin.empty())
781 os << "\\leftmargin "
782 << VSpace(leftmargin).asLyXCommand() << '\n';
783 if (!topmargin.empty())
785 << VSpace(topmargin).asLyXCommand() << '\n';
786 if (!rightmargin.empty())
787 os << "\\rightmargin "
788 << VSpace(rightmargin).asLyXCommand() << '\n';
789 if (!bottommargin.empty())
790 os << "\\bottommargin "
791 << VSpace(bottommargin).asLyXCommand() << '\n';
792 if (!headheight.empty())
793 os << "\\headheight "
794 << VSpace(headheight).asLyXCommand() << '\n';
795 if (!headsep.empty())
797 << VSpace(headsep).asLyXCommand() << '\n';
798 if (!footskip.empty())
800 << VSpace(footskip).asLyXCommand() << '\n';
801 if (!columnsep.empty())
803 << VSpace(columnsep).asLyXCommand() << '\n';
804 os << "\\secnumdepth " << secnumdepth
805 << "\n\\tocdepth " << tocdepth
806 << "\n\\paragraph_separation "
807 << string_paragraph_separation[paragraph_separation]
808 << "\n\\defskip " << getDefSkip().asLyXCommand()
809 << "\n\\quotes_language "
810 << string_quotes_language[quotes_language]
811 << "\n\\papercolumns " << columns
812 << "\n\\papersides " << sides
813 << "\n\\paperpagestyle " << pagestyle << '\n';
814 if (!listings_params.empty())
815 os << "\\listings_params \"" <<
816 InsetListingsParams(listings_params).encodedString() << "\"\n";
817 for (int i = 0; i < 4; ++i) {
818 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
819 if (user_defined_bullet(i).getFont() != -1) {
820 os << "\\bullet " << i << " "
821 << user_defined_bullet(i).getFont() << " "
822 << user_defined_bullet(i).getCharacter() << " "
823 << user_defined_bullet(i).getSize() << "\n";
827 os << "\\bulletLaTeX " << i << " \""
828 << lyx::to_ascii(user_defined_bullet(i).getText())
834 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
835 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
837 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
838 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
839 for (; a_it != a_end; ++a_it) {
840 if (a_it->second.used())
841 os << "\\author " << a_it->second << "\n";
843 os << "\\author " << Author() << "\n";
848 void BufferParams::validate(LaTeXFeatures & features) const
850 features.require(documentClass().requires());
853 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
854 bool xcolorsoul = LaTeXFeatures::isAvailable("soul") &&
855 LaTeXFeatures::isAvailable("xcolor");
857 switch (features.runparams().flavor) {
858 case OutputParams::LATEX:
860 features.require("ct-dvipost");
861 features.require("dvipost");
862 } else if (xcolorsoul) {
863 features.require("ct-xcolor-soul");
864 features.require("soul");
865 features.require("xcolor");
867 features.require("ct-none");
870 case OutputParams::PDFLATEX:
872 features.require("ct-xcolor-soul");
873 features.require("soul");
874 features.require("xcolor");
875 // improves color handling in PDF output
876 features.require("pdfcolmk");
878 features.require("ct-none");
886 // Floats with 'Here definitely' as default setting.
887 if (float_placement.find('H') != string::npos)
888 features.require("float");
890 // AMS Style is at document level
891 if (use_amsmath == package_on
892 || documentClass().provides("amsmath"))
893 features.require("amsmath");
894 if (use_esint == package_on)
895 features.require("esint");
897 // Document-level line spacing
898 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
899 features.require("setspace");
901 // the bullet shapes are buffer level not paragraph level
902 // so they are tested here
903 for (int i = 0; i < 4; ++i) {
904 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
906 int const font = user_defined_bullet(i).getFont();
908 int const c = user_defined_bullet(i).getCharacter();
914 features.require("latexsym");
916 } else if (font == 1) {
917 features.require("amssymb");
918 } else if (font >= 2 && font <= 5) {
919 features.require("pifont");
923 if (pdfoptions().use_hyperref) {
924 features.require("hyperref");
925 // due to interferences with babel and hyperref, the color package has to
926 // be loaded after hyperref when hyperref is used with the colorlinks
927 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
928 if (pdfoptions().colorlinks)
929 features.require("color");
932 if (language->lang() == "vietnamese")
933 features.require("vietnamese");
934 else if (language->lang() == "japanese")
935 features.require("japanese");
938 /// Find out if we need special treatment for babel.
939 static bool needsSpecialBabelCall(LaTeXFeatures const & features)
941 // FIXME: don't hardcode this!!
942 // If Vietnamese is used, babel must directly be loaded with the
943 // language options, see
944 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
946 // viet = string::npos when not found
947 // the same is for all other languages that are not directly supported by
948 // babel, but where LaTeX-packages add babel support.
949 // this is currently the case for Latvian, Lithuanian, and Mongolian
951 // If Japanese is used, babel must directly be loaded with the
952 // language options, see
953 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
954 return !lyxrc.language_global_options
955 || features.hasLanguage("vietnam")
956 || features.hasLanguage("latvian")
957 || features.hasLanguage("japanese")
958 || features.hasLanguage("lithuanian")
959 || features.hasLanguage("mongolian");
962 /// set up if and how babel is called
963 static docstring babelCall(LaTeXFeatures const & features,
964 string const & lang_opts)
966 string babel_call = lyxrc.language_package;
967 if (babel_call != "\\usepackage{babel}")
968 return from_utf8(babel_call);
969 // suppress the babel call when there is no babel language defined
970 // for the document language in the lib/languages file and if no
971 // other languages are used (lang_opts is then empty)
972 if (!features.hasLanguages())
975 if (needsSpecialBabelCall(features))
976 babel_call = "\\usepackage[" + lang_opts + "]{babel}";
978 return from_utf8(babel_call);
982 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
983 TexRow & texrow) const
985 os << "\\documentclass";
987 DocumentClass const & tclass = documentClass();
989 ostringstream clsoptions; // the document class options.
991 if (tokenPos(tclass.opt_fontsize(),
992 '|', fontsize) >= 0) {
993 // only write if existing in list (and not default)
994 clsoptions << fontsize << "pt,";
997 // custom, A3, B3 and B4 paper sizes need geometry
998 bool nonstandard_papersize = papersize == PAPER_B3
999 || papersize == PAPER_B4
1000 || papersize == PAPER_A3
1001 || papersize == PAPER_CUSTOM;
1003 if (!use_geometry) {
1004 switch (papersize) {
1006 clsoptions << "a4paper,";
1008 case PAPER_USLETTER:
1009 clsoptions << "letterpaper,";
1012 clsoptions << "a5paper,";
1015 clsoptions << "b5paper,";
1017 case PAPER_USEXECUTIVE:
1018 clsoptions << "executivepaper,";
1021 clsoptions << "legalpaper,";
1033 if (sides != tclass.sides()) {
1036 clsoptions << "oneside,";
1039 clsoptions << "twoside,";
1045 if (columns != tclass.columns()) {
1047 clsoptions << "twocolumn,";
1049 clsoptions << "onecolumn,";
1053 && orientation == ORIENTATION_LANDSCAPE)
1054 clsoptions << "landscape,";
1056 // language should be a parameter to \documentclass
1057 if (language->babel() == "hebrew"
1058 && default_language->babel() != "hebrew")
1059 // This seems necessary
1060 features.useLanguage(default_language);
1062 ostringstream language_options;
1063 bool const use_babel = features.useBabel();
1065 language_options << features.getLanguages();
1066 if (!language->babel().empty()) {
1067 if (!language_options.str().empty())
1068 language_options << ',';
1069 language_options << language->babel();
1071 if (!language_options.str().empty()
1072 && !needsSpecialBabelCall(features))
1073 clsoptions << language_options.str() << ',';
1076 // the user-defined options
1077 if (!options.empty()) {
1078 clsoptions << options << ',';
1081 string strOptions(clsoptions.str());
1082 if (!strOptions.empty()) {
1083 strOptions = rtrim(strOptions, ",");
1085 os << '[' << from_utf8(strOptions) << ']';
1088 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1090 // end of \documentclass defs
1092 // font selection must be done before loading fontenc.sty
1093 string const fonts =
1094 loadFonts(fontsRoman, fontsSans,
1095 fontsTypewriter, fontsSC, fontsOSF,
1096 fontsSansScale, fontsTypewriterScale);
1097 if (!fonts.empty()) {
1098 os << from_ascii(fonts);
1101 if (fontsDefaultFamily != "default")
1102 os << "\\renewcommand{\\familydefault}{\\"
1103 << from_ascii(fontsDefaultFamily) << "}\n";
1105 // set font encoding
1106 // this one is not per buffer
1107 // for arabic_arabi and farsi we also need to load the LAE and
1109 if (lyxrc.fontenc != "default" && language->lang() != "japanese") {
1110 if (language->lang() == "arabic_arabi"
1111 || language->lang() == "farsi") {
1112 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1113 << ",LFE,LAE]{fontenc}\n";
1116 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1122 // handle inputenc etc.
1123 writeEncodingPreamble(os, features, texrow);
1125 if (!listings_params.empty() || features.isRequired("listings")) {
1126 os << "\\usepackage{listings}\n";
1129 if (!listings_params.empty()) {
1131 // do not test validity because listings_params is
1132 // supposed to be valid
1134 InsetListingsParams(listings_params).separatedParams(true);
1135 // we can't support all packages, but we should load the color package
1136 if (par.find("\\color", 0) != string::npos)
1137 features.require("color");
1138 os << from_utf8(par);
1139 // count the number of newlines
1140 for (size_t i = 0; i < par.size(); ++i)
1146 if (use_geometry || nonstandard_papersize) {
1147 os << "\\usepackage{geometry}\n";
1149 os << "\\geometry{verbose";
1150 if (orientation == ORIENTATION_LANDSCAPE)
1152 switch (papersize) {
1154 if (!paperwidth.empty())
1155 os << ",paperwidth="
1156 << from_ascii(paperwidth);
1157 if (!paperheight.empty())
1158 os << ",paperheight="
1159 << from_ascii(paperheight);
1161 case PAPER_USLETTER:
1162 os << ",letterpaper";
1165 os << ",legalpaper";
1167 case PAPER_USEXECUTIVE:
1168 os << ",executivepaper";
1189 // default papersize ie PAPER_DEFAULT
1190 switch (lyxrc.default_papersize) {
1191 case PAPER_DEFAULT: // keep compiler happy
1192 case PAPER_USLETTER:
1193 os << ",letterpaper";
1196 os << ",legalpaper";
1198 case PAPER_USEXECUTIVE:
1199 os << ",executivepaper";
1219 if (!topmargin.empty())
1220 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1221 if (!bottommargin.empty())
1222 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1223 if (!leftmargin.empty())
1224 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1225 if (!rightmargin.empty())
1226 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1227 if (!headheight.empty())
1228 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1229 if (!headsep.empty())
1230 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1231 if (!footskip.empty())
1232 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1233 if (!columnsep.empty())
1234 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1237 } else if (orientation == ORIENTATION_LANDSCAPE) {
1238 features.require("papersize");
1241 if (tokenPos(tclass.opt_pagestyle(),
1242 '|', pagestyle) >= 0) {
1243 if (pagestyle == "fancy") {
1244 os << "\\usepackage{fancyhdr}\n";
1247 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1251 // Only if class has a ToC hierarchy
1252 if (tclass.hasTocLevels()) {
1253 if (secnumdepth != tclass.secnumdepth()) {
1254 os << "\\setcounter{secnumdepth}{"
1259 if (tocdepth != tclass.tocdepth()) {
1260 os << "\\setcounter{tocdepth}{"
1267 if (paragraph_separation) {
1268 switch (getDefSkip().kind()) {
1269 case VSpace::SMALLSKIP:
1270 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1272 case VSpace::MEDSKIP:
1273 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1275 case VSpace::BIGSKIP:
1276 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1278 case VSpace::LENGTH:
1279 os << "\\setlength{\\parskip}{"
1280 << from_utf8(getDefSkip().length().asLatexString())
1283 default: // should never happen // Then delete it.
1284 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1289 os << "\\setlength{\\parindent}{0pt}\n";
1293 // Now insert the LyX specific LaTeX commands...
1294 docstring lyxpreamble;
1296 // due to interferences with babel and hyperref, the color package has to
1297 // be loaded (when it is not already loaded) before babel when hyperref
1298 // is used with the colorlinks option, see
1299 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1300 // we decided therefore to load color always before babel, see
1301 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1302 lyxpreamble += from_ascii(features.getColorOptions());
1304 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1306 && (features.isRequired("jurabib")
1307 || features.isRequired("hyperref")
1308 || features.isRequired("vietnamese")
1309 || features.isRequired("japanese") ) ) {
1311 lyxpreamble += babelCall(features, language_options.str()) + '\n';
1312 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1315 // The optional packages;
1316 lyxpreamble += from_ascii(features.getPackages());
1319 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1322 // * Hyperref manual: "Make sure it comes last of your loaded
1323 // packages, to give it a fighting chance of not being over-written,
1324 // since its job is to redefine many LaTeX commands."
1325 // * Email from Heiko Oberdiek: "It is usually better to load babel
1326 // before hyperref. Then hyperref has a chance to detect babel.
1327 // * Has to be loaded before the "LyX specific LaTeX commands" to
1328 // avoid errors with algorithm floats.
1329 // use hyperref explicitely when it is required
1330 if (features.isRequired("hyperref")) {
1331 odocstringstream oss;
1332 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1333 lyxpreamble += oss.str();
1336 // Will be surrounded by \makeatletter and \makeatother when needed
1337 docstring atlyxpreamble;
1339 // Some macros LyX will need
1340 docstring tmppreamble(from_ascii(features.getMacros()));
1342 if (!tmppreamble.empty())
1343 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1344 "LyX specific LaTeX commands.\n"
1345 + tmppreamble + '\n';
1347 // the text class specific preamble
1348 tmppreamble = features.getTClassPreamble();
1349 if (!tmppreamble.empty())
1350 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1351 "Textclass specific LaTeX commands.\n"
1352 + tmppreamble + '\n';
1354 /* the user-defined preamble */
1355 if (!preamble.empty())
1357 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1358 "User specified LaTeX commands.\n"
1359 + from_utf8(preamble) + '\n';
1361 // subfig loads internally the LaTeX package "caption". As
1362 // caption is a very popular package, users will load it in
1363 // the preamble. Therefore we must load subfig behind the
1364 // user-defined preamble and check if the caption package was
1365 // loaded or not. For the case that caption is loaded before
1366 // subfig, there is the subfig option "caption=false". This
1367 // option also works when a koma-script class is used and
1368 // koma's own caption commands are used instead of caption. We
1369 // use \PassOptionsToPackage here because the user could have
1370 // already loaded subfig in the preamble.
1371 if (features.isRequired("subfig")) {
1372 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1373 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1374 "\\usepackage{subfig}\n";
1377 // Itemize bullet settings need to be last in case the user
1378 // defines their own bullets that use a package included
1379 // in the user-defined preamble -- ARRae
1380 // Actually it has to be done much later than that
1381 // since some packages like frenchb make modifications
1382 // at \begin{document} time -- JMarc
1383 docstring bullets_def;
1384 for (int i = 0; i < 4; ++i) {
1385 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1386 if (bullets_def.empty())
1387 bullets_def += "\\AtBeginDocument{\n";
1388 bullets_def += " \\def\\labelitemi";
1390 // `i' is one less than the item to modify
1397 bullets_def += "ii";
1403 bullets_def += '{' +
1404 user_defined_bullet(i).getText()
1409 if (!bullets_def.empty())
1410 atlyxpreamble += bullets_def + "}\n\n";
1412 if (atlyxpreamble.find(from_ascii("@")) != docstring::npos)
1413 lyxpreamble += "\n\\makeatletter\n"
1414 + atlyxpreamble + "\\makeatother\n\n";
1416 lyxpreamble += '\n' + atlyxpreamble;
1418 // We try to load babel late, in case it interferes with other packages.
1419 // Jurabib and Hyperref have to be called after babel, though.
1420 if (use_babel && !features.isRequired("jurabib")
1421 && !features.isRequired("hyperref")
1422 && !features.isRequired("vietnamese")
1423 && !features.isRequired("japanese")) {
1425 lyxpreamble += babelCall(features, language_options.str()) + '\n';
1426 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1430 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1431 for (int j = 0; j != nlines; ++j) {
1440 void BufferParams::useClassDefaults()
1442 DocumentClass const & tclass = documentClass();
1444 sides = tclass.sides();
1445 columns = tclass.columns();
1446 pagestyle = tclass.pagestyle();
1447 options = tclass.options();
1448 // Only if class has a ToC hierarchy
1449 if (tclass.hasTocLevels()) {
1450 secnumdepth = tclass.secnumdepth();
1451 tocdepth = tclass.tocdepth();
1456 bool BufferParams::hasClassDefaults() const
1458 DocumentClass const & tclass = documentClass();
1460 return sides == tclass.sides()
1461 && columns == tclass.columns()
1462 && pagestyle == tclass.pagestyle()
1463 && options == tclass.options()
1464 && secnumdepth == tclass.secnumdepth()
1465 && tocdepth == tclass.tocdepth();
1469 DocumentClass const & BufferParams::documentClass() const
1475 DocumentClass const * BufferParams::documentClassPtr() const {
1480 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1481 // evil, but this function is evil
1482 doc_class_ = const_cast<DocumentClass *>(tc);
1486 bool BufferParams::setBaseClass(string const & classname)
1488 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1489 LayoutFileList & bcl = LayoutFileList::get();
1490 if (!bcl.haveClass(classname)) {
1492 bformat(_("The document class %1$s could not be found. "
1493 "A default textclass with default layouts will be used. "
1494 "LyX might not be able to produce output unless a correct "
1495 "textclass is selected from the document settings dialog."),
1496 from_utf8(classname));
1497 frontend::Alert::error(_("Document class not found"), s);
1498 bcl.addEmptyClass(classname);
1501 bool const success = bcl[classname].load();
1504 bformat(_("The document class %1$s could not be loaded."),
1505 from_utf8(classname));
1506 frontend::Alert::error(_("Could not load class"), s);
1510 pimpl_->baseClass_ = classname;
1512 // add any required modules not already in use
1513 list<string> const & mods = baseClass()->defaultModules();
1514 list<string>::const_iterator mit = mods.begin();
1515 list<string>::const_iterator men = mods.end();
1516 for (; mit != men; mit++) {
1517 string const & modName = *mit;
1518 // see if we're already in use
1519 if (find(layoutModules_.begin(), layoutModules_.end(), modName) !=
1520 layoutModules_.end()) {
1521 LYXERR(Debug::TCLASS, "Default module `" << modName <<
1522 "' not added because already used.");
1525 // make sure the user hasn't removed it
1526 if (find(removedModules_.begin(), removedModules_.end(), modName) !=
1527 removedModules_.end()) {
1528 LYXERR(Debug::TCLASS, "Default module `" << modName <<
1529 "' not added because removed by user.");
1532 // Now we want to check the list of selected modules to see if any of them
1533 // exclude this one.
1534 bool foundit = false;
1535 // so iterate over the selected modules...
1536 LayoutModuleList::const_iterator lit = layoutModules_.begin();
1537 LayoutModuleList::const_iterator len = layoutModules_.end();
1538 for (; lit != len; lit++) {
1539 LyXModule * lm = moduleList[*lit];
1542 vector<string> const & exc = lm->getExcludedModules();
1543 // ...and see if this one excludes us.
1544 if (find(exc.begin(), exc.end(), modName) != exc.end()) {
1546 LYXERR(Debug::TCLASS, "Default module `" << modName <<
1547 "' not added because excluded by loaded module `" <<
1553 LYXERR(Debug::TCLASS, "Default module `" << modName << "' added.");
1554 layoutModules_.push_back(modName);
1561 LayoutFile const * BufferParams::baseClass() const
1563 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1564 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1570 LayoutFileIndex const & BufferParams::baseClassID() const
1572 return pimpl_->baseClass_;
1576 void BufferParams::makeDocumentClass()
1581 doc_class_ = &(DocumentClassBundle::get().newClass(*baseClass()));
1583 // FIXME It might be worth loading the children's modules here,
1584 // just as we load their bibliographies and such, instead of just
1585 // doing a check in InsetInclude.
1586 LayoutModuleList::const_iterator it = layoutModules_.begin();
1587 for (; it != layoutModules_.end(); it++) {
1588 string const modName = *it;
1589 LyXModule * lm = moduleList[modName];
1591 docstring const msg =
1592 bformat(_("The module %1$s has been requested by\n"
1593 "this document but has not been found in the list of\n"
1594 "available modules. If you recently installed it, you\n"
1595 "probably need to reconfigure LyX.\n"), from_utf8(modName));
1596 frontend::Alert::warning(_("Module not available"),
1597 msg + _("Some layouts may not be available."));
1598 LYXERR0("BufferParams::makeDocumentClass(): Module " <<
1599 modName << " requested but not found in module list.");
1602 if (!lm->isAvailable()) {
1603 docstring const msg =
1604 bformat(_("The module %1$s requires a package that is\n"
1605 "not available in your LaTeX installation. LaTeX output\n"
1606 "may not be possible.\n"), from_utf8(modName));
1607 frontend::Alert::warning(_("Package not available"), msg);
1609 FileName layout_file = libFileSearch("layouts", lm->getFilename());
1610 if (!doc_class_->read(layout_file, TextClass::MODULE)) {
1611 docstring const msg =
1612 bformat(_("Error reading module %1$s\n"), from_utf8(modName));
1613 frontend::Alert::warning(_("Read Error"), msg);
1616 if (!local_layout.empty()) {
1617 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1618 docstring const msg = _("Error reading internal layout information");
1619 frontend::Alert::warning(_("Read Error"), msg);
1625 bool BufferParams::addLayoutModule(string const & modName)
1627 LayoutModuleList::const_iterator it = layoutModules_.begin();
1628 LayoutModuleList::const_iterator end = layoutModules_.end();
1629 for (; it != end; it++)
1632 layoutModules_.push_back(modName);
1637 Font const BufferParams::getFont() const
1639 FontInfo f = documentClass().defaultfont();
1640 if (fontsDefaultFamily == "rmdefault")
1641 f.setFamily(ROMAN_FAMILY);
1642 else if (fontsDefaultFamily == "sfdefault")
1643 f.setFamily(SANS_FAMILY);
1644 else if (fontsDefaultFamily == "ttdefault")
1645 f.setFamily(TYPEWRITER_FAMILY);
1646 return Font(f, language);
1650 void BufferParams::readPreamble(Lexer & lex)
1652 if (lex.getString() != "\\begin_preamble")
1653 lyxerr << "Error (BufferParams::readPreamble):"
1654 "consistency check failed." << endl;
1656 preamble = lex.getLongString("\\end_preamble");
1660 void BufferParams::readLocalLayout(Lexer & lex)
1662 if (lex.getString() != "\\begin_local_layout")
1663 lyxerr << "Error (BufferParams::readLocalLayout):"
1664 "consistency check failed." << endl;
1666 local_layout = lex.getLongString("\\end_local_layout");
1670 void BufferParams::readLanguage(Lexer & lex)
1672 if (!lex.next()) return;
1674 string const tmptok = lex.getString();
1676 // check if tmptok is part of tex_babel in tex-defs.h
1677 language = languages.getLanguage(tmptok);
1679 // Language tmptok was not found
1680 language = default_language;
1681 lyxerr << "Warning: Setting language `"
1682 << tmptok << "' to `" << language->lang()
1688 void BufferParams::readGraphicsDriver(Lexer & lex)
1693 string const tmptok = lex.getString();
1694 // check if tmptok is part of tex_graphics in tex_defs.h
1697 string const test = tex_graphics[n++];
1699 if (test == tmptok) {
1700 graphicsDriver = tmptok;
1705 "Warning: graphics driver `$$Token' not recognized!\n"
1706 " Setting graphics driver to `default'.\n");
1707 graphicsDriver = "default";
1714 void BufferParams::readBullets(Lexer & lex)
1719 int const index = lex.getInteger();
1721 int temp_int = lex.getInteger();
1722 user_defined_bullet(index).setFont(temp_int);
1723 temp_bullet(index).setFont(temp_int);
1725 user_defined_bullet(index).setCharacter(temp_int);
1726 temp_bullet(index).setCharacter(temp_int);
1728 user_defined_bullet(index).setSize(temp_int);
1729 temp_bullet(index).setSize(temp_int);
1733 void BufferParams::readBulletsLaTeX(Lexer & lex)
1735 // The bullet class should be able to read this.
1738 int const index = lex.getInteger();
1740 docstring const temp_str = lex.getDocString();
1742 user_defined_bullet(index).setText(temp_str);
1743 temp_bullet(index).setText(temp_str);
1747 void BufferParams::readModules(Lexer & lex)
1749 if (!lex.eatLine()) {
1750 lyxerr << "Error (BufferParams::readModules):"
1751 "Unexpected end of input." << endl;
1755 string mod = lex.getString();
1756 if (mod == "\\end_modules")
1758 addLayoutModule(mod);
1764 void BufferParams::readRemovedModules(Lexer & lex)
1766 if (!lex.eatLine()) {
1767 lyxerr << "Error (BufferParams::readRemovedModules):"
1768 "Unexpected end of input." << endl;
1772 string mod = lex.getString();
1773 if (mod == "\\end_removed_modules")
1775 removedModules_.insert(mod);
1778 // now we want to remove any removed modules that were previously
1779 // added. normally, that will be because default modules were added in
1780 // setBaseClass(), which gets called when \textclass is read at the
1781 // start of the read.
1782 set<string>::const_iterator rit = removedModules_.begin();
1783 set<string>::const_iterator const ren = removedModules_.end();
1784 for (; rit != ren; rit++) {
1785 LayoutModuleList::iterator const mit = layoutModules_.begin();
1786 LayoutModuleList::iterator const men = layoutModules_.end();
1787 LayoutModuleList::iterator found = find(mit, men, *rit);
1790 layoutModules_.erase(found);
1795 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1797 char real_papersize = papersize;
1798 if (real_papersize == PAPER_DEFAULT)
1799 real_papersize = lyxrc.default_papersize;
1801 switch (real_papersize) {
1803 // could be anything, so don't guess
1805 case PAPER_CUSTOM: {
1806 if (purpose == XDVI && !paperwidth.empty() &&
1807 !paperheight.empty()) {
1808 // heightxwidth<unit>
1809 string first = paperwidth;
1810 string second = paperheight;
1811 if (orientation == ORIENTATION_LANDSCAPE)
1814 return first.erase(first.length() - 2)
1826 // dvips and dvipdfm do not know this
1827 if (purpose == DVIPS || purpose == DVIPDFM)
1831 // dvipdfm does not know this
1832 if (purpose == DVIPDFM)
1836 // dvipdfm does not know this
1837 if (purpose == DVIPDFM)
1840 case PAPER_USEXECUTIVE:
1841 // dvipdfm does not know this
1842 if (purpose == DVIPDFM)
1847 case PAPER_USLETTER:
1849 if (purpose == XDVI)
1856 string const BufferParams::dvips_options() const
1861 && papersize == PAPER_CUSTOM
1862 && !lyxrc.print_paper_dimension_flag.empty()
1863 && !paperwidth.empty()
1864 && !paperheight.empty()) {
1865 // using a custom papersize
1866 result = lyxrc.print_paper_dimension_flag;
1867 result += ' ' + paperwidth;
1868 result += ',' + paperheight;
1870 string const paper_option = paperSizeName(DVIPS);
1871 if (!paper_option.empty() && (paper_option != "letter" ||
1872 orientation != ORIENTATION_LANDSCAPE)) {
1873 // dvips won't accept -t letter -t landscape.
1874 // In all other cases, include the paper size
1876 result = lyxrc.print_paper_flag;
1877 result += ' ' + paper_option;
1880 if (orientation == ORIENTATION_LANDSCAPE &&
1881 papersize != PAPER_CUSTOM)
1882 result += ' ' + lyxrc.print_landscape_flag;
1887 void BufferParams::writeEncodingPreamble(odocstream & os,
1888 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 os << "\\usepackage{CJK}\n";
1930 } else if (inputenc != "default") {
1931 switch (encoding().package()) {
1932 case Encoding::none:
1933 case Encoding::japanese:
1935 case Encoding::inputenc:
1936 // do not load inputenc if japanese is used
1937 if (features.isRequired("japanese"))
1939 os << "\\usepackage[" << from_ascii(inputenc)
1944 os << "\\usepackage{CJK}\n";
1950 // The encoding "armscii8" (for Armenian) is only available when
1951 // the package "armtex" is loaded.
1952 if (language->encoding()->latexName() == "armscii8"
1953 || inputenc == "armscii8") {
1954 os << "\\usepackage{armtex}\n";
1960 string const BufferParams::loadFonts(string const & rm,
1961 string const & sf, string const & tt,
1962 bool const & sc, bool const & osf,
1963 int const & sfscale, int const & ttscale) const
1965 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1966 several packages have been replaced by others, that might not
1967 be installed on every system. We have to take care for that
1968 (see psnfss.pdf). We try to support all psnfss fonts as well
1969 as the fonts that have become de facto standard in the LaTeX
1970 world (e.g. Latin Modern). We do not support obsolete fonts
1971 (like PSLatex). In general, it should be possible to mix any
1972 rm font with any sf or tt font, respectively. (JSpitzm)
1974 -- separate math fonts.
1977 if (rm == "default" && sf == "default" && tt == "default")
1984 // Computer Modern (must be explicitely selectable -- there might be classes
1985 // that define a different default font!
1987 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1988 // osf for Computer Modern needs eco.sty
1990 os << "\\usepackage{eco}\n";
1992 // Latin Modern Roman
1993 else if (rm == "lmodern")
1994 os << "\\usepackage{lmodern}\n";
1996 else if (rm == "ae") {
1997 // not needed when using OT1 font encoding.
1998 if (lyxrc.fontenc != "default")
1999 os << "\\usepackage{ae,aecompl}\n";
2002 else if (rm == "times") {
2003 // try to load the best available package
2004 if (LaTeXFeatures::isAvailable("mathptmx"))
2005 os << "\\usepackage{mathptmx}\n";
2006 else if (LaTeXFeatures::isAvailable("mathptm"))
2007 os << "\\usepackage{mathptm}\n";
2009 os << "\\usepackage{times}\n";
2012 else if (rm == "palatino") {
2013 // try to load the best available package
2014 if (LaTeXFeatures::isAvailable("mathpazo")) {
2015 os << "\\usepackage";
2021 // "osf" includes "sc"!
2025 os << "{mathpazo}\n";
2027 else if (LaTeXFeatures::isAvailable("mathpple"))
2028 os << "\\usepackage{mathpple}\n";
2030 os << "\\usepackage{palatino}\n";
2033 else if (rm == "utopia") {
2034 // fourier supersedes utopia.sty, but does
2035 // not work with OT1 encoding.
2036 if (LaTeXFeatures::isAvailable("fourier")
2037 && lyxrc.fontenc != "default") {
2038 os << "\\usepackage";
2049 os << "{fourier}\n";
2052 os << "\\usepackage{utopia}\n";
2054 // Bera (complete fontset)
2055 else if (rm == "bera" && sf == "default" && tt == "default")
2056 os << "\\usepackage{bera}\n";
2058 else if (rm != "default")
2059 os << "\\usepackage" << "{" << rm << "}\n";
2062 // Helvetica, Bera Sans
2063 if (sf == "helvet" || sf == "berasans") {
2065 os << "\\usepackage[scaled=" << float(sfscale) / 100
2066 << "]{" << sf << "}\n";
2068 os << "\\usepackage{" << sf << "}\n";
2071 else if (sf == "avant")
2072 os << "\\usepackage{" << sf << "}\n";
2073 // Computer Modern, Latin Modern, CM Bright
2074 else if (sf != "default")
2075 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2077 // monospaced/typewriter
2078 // Courier, LuxiMono
2079 if (tt == "luximono" || tt == "beramono") {
2081 os << "\\usepackage[scaled=" << float(ttscale) / 100
2082 << "]{" << tt << "}\n";
2084 os << "\\usepackage{" << tt << "}\n";
2087 else if (tt == "courier" )
2088 os << "\\usepackage{" << tt << "}\n";
2089 // Computer Modern, Latin Modern, CM Bright
2090 else if (tt != "default")
2091 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2097 Encoding const & BufferParams::encoding() const
2099 if (inputenc == "auto" || inputenc == "default")
2100 return *language->encoding();
2101 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2104 LYXERR0("Unknown inputenc value `" << inputenc
2105 << "'. Using `auto' instead.");
2106 return *language->encoding();
2110 CiteEngine BufferParams::citeEngine() const
2112 // FIXME the class should provide the numerical/
2113 // authoryear choice
2114 if (documentClass().provides("natbib")
2115 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2116 return ENGINE_NATBIB_AUTHORYEAR;
2117 return cite_engine_;
2121 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2123 cite_engine_ = cite_engine;