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");
939 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
940 TexRow & texrow) const
942 os << "\\documentclass";
944 DocumentClass const & tclass = documentClass();
946 ostringstream clsoptions; // the document class options.
948 if (tokenPos(tclass.opt_fontsize(),
949 '|', fontsize) >= 0) {
950 // only write if existing in list (and not default)
951 clsoptions << fontsize << "pt,";
954 // custom, A3, B3 and B4 paper sizes need geometry
955 bool nonstandard_papersize = papersize == PAPER_B3
956 || papersize == PAPER_B4
957 || papersize == PAPER_A3
958 || papersize == PAPER_CUSTOM;
963 clsoptions << "a4paper,";
966 clsoptions << "letterpaper,";
969 clsoptions << "a5paper,";
972 clsoptions << "b5paper,";
974 case PAPER_USEXECUTIVE:
975 clsoptions << "executivepaper,";
978 clsoptions << "legalpaper,";
990 if (sides != tclass.sides()) {
993 clsoptions << "oneside,";
996 clsoptions << "twoside,";
1002 if (columns != tclass.columns()) {
1004 clsoptions << "twocolumn,";
1006 clsoptions << "onecolumn,";
1010 && orientation == ORIENTATION_LANDSCAPE)
1011 clsoptions << "landscape,";
1013 // language should be a parameter to \documentclass
1014 if (language->babel() == "hebrew"
1015 && default_language->babel() != "hebrew")
1016 // This seems necessary
1017 features.useLanguage(default_language);
1019 ostringstream language_options;
1020 bool const use_babel = features.useBabel();
1022 language_options << features.getLanguages();
1023 if (!language->babel().empty()) {
1024 if (!language_options.str().empty())
1025 language_options << ',';
1026 language_options << language->babel();
1028 // if Vietnamese is used, babel must directly be loaded
1029 // with language options, not in the class options, see
1030 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1031 size_t viet = language_options.str().find("vietnam");
1032 // viet = string::npos when not found
1033 // the same is for all other languages that are not directly supported by
1034 // babel, but where LaTeX-packages add babel support.
1035 // this is currently the case for Latvian, Lithuanian, and Mongolian
1036 size_t latvian = language_options.str().find("latvian");
1037 size_t lithu = language_options.str().find("lithuanian");
1038 size_t mongo = language_options.str().find("mongolian");
1039 // if Japanese is used, babel must directly be loaded
1040 // with language options, not in the class options, see
1041 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1042 size_t japan = language_options.str().find("japanese");
1043 if (lyxrc.language_global_options && !language_options.str().empty()
1044 && viet == string::npos && japan == string::npos
1045 && latvian == string::npos && lithu == string::npos
1046 && mongo == string::npos)
1047 clsoptions << language_options.str() << ',';
1050 // the user-defined options
1051 if (!options.empty()) {
1052 clsoptions << options << ',';
1055 string strOptions(clsoptions.str());
1056 if (!strOptions.empty()) {
1057 strOptions = rtrim(strOptions, ",");
1059 os << '[' << from_utf8(strOptions) << ']';
1062 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1064 // end of \documentclass defs
1066 // font selection must be done before loading fontenc.sty
1067 string const fonts =
1068 loadFonts(fontsRoman, fontsSans,
1069 fontsTypewriter, fontsSC, fontsOSF,
1070 fontsSansScale, fontsTypewriterScale);
1071 if (!fonts.empty()) {
1072 os << from_ascii(fonts);
1075 if (fontsDefaultFamily != "default")
1076 os << "\\renewcommand{\\familydefault}{\\"
1077 << from_ascii(fontsDefaultFamily) << "}\n";
1079 // set font encoding
1080 // this one is not per buffer
1081 // for arabic_arabi and farsi we also need to load the LAE and
1083 if (lyxrc.fontenc != "default" && language->lang() != "japanese") {
1084 if (language->lang() == "arabic_arabi"
1085 || language->lang() == "farsi") {
1086 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1087 << ",LFE,LAE]{fontenc}\n";
1090 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1096 // handle inputenc etc.
1097 writeEncodingPreamble(os, features, texrow);
1099 if (!listings_params.empty() || features.isRequired("listings")) {
1100 os << "\\usepackage{listings}\n";
1103 if (!listings_params.empty()) {
1105 // do not test validity because listings_params is
1106 // supposed to be valid
1108 InsetListingsParams(listings_params).separatedParams(true);
1109 // we can't support all packages, but we should load the color package
1110 if (par.find("\\color", 0) != string::npos)
1111 features.require("color");
1112 os << from_utf8(par);
1113 // count the number of newlines
1114 for (size_t i = 0; i < par.size(); ++i)
1120 if (use_geometry || nonstandard_papersize) {
1121 os << "\\usepackage{geometry}\n";
1123 os << "\\geometry{verbose";
1124 if (orientation == ORIENTATION_LANDSCAPE)
1126 switch (papersize) {
1128 if (!paperwidth.empty())
1129 os << ",paperwidth="
1130 << from_ascii(paperwidth);
1131 if (!paperheight.empty())
1132 os << ",paperheight="
1133 << from_ascii(paperheight);
1135 case PAPER_USLETTER:
1136 os << ",letterpaper";
1139 os << ",legalpaper";
1141 case PAPER_USEXECUTIVE:
1142 os << ",executivepaper";
1163 // default papersize ie PAPER_DEFAULT
1164 switch (lyxrc.default_papersize) {
1165 case PAPER_DEFAULT: // keep compiler happy
1166 case PAPER_USLETTER:
1167 os << ",letterpaper";
1170 os << ",legalpaper";
1172 case PAPER_USEXECUTIVE:
1173 os << ",executivepaper";
1193 if (!topmargin.empty())
1194 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1195 if (!bottommargin.empty())
1196 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1197 if (!leftmargin.empty())
1198 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1199 if (!rightmargin.empty())
1200 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1201 if (!headheight.empty())
1202 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1203 if (!headsep.empty())
1204 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1205 if (!footskip.empty())
1206 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1207 if (!columnsep.empty())
1208 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1211 } else if (orientation == ORIENTATION_LANDSCAPE) {
1212 features.require("papersize");
1215 if (tokenPos(tclass.opt_pagestyle(),
1216 '|', pagestyle) >= 0) {
1217 if (pagestyle == "fancy") {
1218 os << "\\usepackage{fancyhdr}\n";
1221 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1225 // Only if class has a ToC hierarchy
1226 if (tclass.hasTocLevels()) {
1227 if (secnumdepth != tclass.secnumdepth()) {
1228 os << "\\setcounter{secnumdepth}{"
1233 if (tocdepth != tclass.tocdepth()) {
1234 os << "\\setcounter{tocdepth}{"
1241 if (paragraph_separation) {
1242 switch (getDefSkip().kind()) {
1243 case VSpace::SMALLSKIP:
1244 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1246 case VSpace::MEDSKIP:
1247 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1249 case VSpace::BIGSKIP:
1250 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1252 case VSpace::LENGTH:
1253 os << "\\setlength{\\parskip}{"
1254 << from_utf8(getDefSkip().length().asLatexString())
1257 default: // should never happen // Then delete it.
1258 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1263 os << "\\setlength{\\parindent}{0pt}\n";
1267 // Now insert the LyX specific LaTeX commands...
1268 docstring lyxpreamble;
1270 // due to interferences with babel and hyperref, the color package has to
1271 // be loaded (when it is not already loaded) before babel when hyperref
1272 // is used with the colorlinks option, see
1273 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1274 // we decided therefore to load color always before babel, see
1275 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1276 lyxpreamble += from_ascii(features.getColorOptions());
1278 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1280 && (features.isRequired("jurabib")
1281 || features.isRequired("hyperref")
1282 || features.isRequired("vietnamese")
1283 || features.isRequired("japanese") ) ) {
1285 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1286 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1289 // The optional packages;
1290 lyxpreamble += from_ascii(features.getPackages());
1293 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1296 // * Hyperref manual: "Make sure it comes last of your loaded
1297 // packages, to give it a fighting chance of not being over-written,
1298 // since its job is to redefine many LaTeX commands."
1299 // * Email from Heiko Oberdiek: "It is usually better to load babel
1300 // before hyperref. Then hyperref has a chance to detect babel.
1301 // * Has to be loaded before the "LyX specific LaTeX commands" to
1302 // avoid errors with algorithm floats.
1303 // use hyperref explicitely when it is required
1304 if (features.isRequired("hyperref")) {
1305 odocstringstream oss;
1306 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1307 lyxpreamble += oss.str();
1310 // Will be surrounded by \makeatletter and \makeatother when needed
1311 docstring atlyxpreamble;
1313 // Some macros LyX will need
1314 docstring tmppreamble(from_ascii(features.getMacros()));
1316 if (!tmppreamble.empty())
1317 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1318 "LyX specific LaTeX commands.\n"
1319 + tmppreamble + '\n';
1321 // the text class specific preamble
1322 tmppreamble = features.getTClassPreamble();
1323 if (!tmppreamble.empty())
1324 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1325 "Textclass specific LaTeX commands.\n"
1326 + tmppreamble + '\n';
1328 /* the user-defined preamble */
1329 if (!preamble.empty())
1331 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1332 "User specified LaTeX commands.\n"
1333 + from_utf8(preamble) + '\n';
1335 // subfig loads internally the LaTeX package "caption". As
1336 // caption is a very popular package, users will load it in
1337 // the preamble. Therefore we must load subfig behind the
1338 // user-defined preamble and check if the caption package was
1339 // loaded or not. For the case that caption is loaded before
1340 // subfig, there is the subfig option "caption=false". This
1341 // option also works when a koma-script class is used and
1342 // koma's own caption commands are used instead of caption. We
1343 // use \PassOptionsToPackage here because the user could have
1344 // already loaded subfig in the preamble.
1345 if (features.isRequired("subfig")) {
1346 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1347 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1348 "\\usepackage{subfig}\n";
1351 // Itemize bullet settings need to be last in case the user
1352 // defines their own bullets that use a package included
1353 // in the user-defined preamble -- ARRae
1354 // Actually it has to be done much later than that
1355 // since some packages like frenchb make modifications
1356 // at \begin{document} time -- JMarc
1357 docstring bullets_def;
1358 for (int i = 0; i < 4; ++i) {
1359 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1360 if (bullets_def.empty())
1361 bullets_def += "\\AtBeginDocument{\n";
1362 bullets_def += " \\def\\labelitemi";
1364 // `i' is one less than the item to modify
1371 bullets_def += "ii";
1377 bullets_def += '{' +
1378 user_defined_bullet(i).getText()
1383 if (!bullets_def.empty())
1384 atlyxpreamble += bullets_def + "}\n\n";
1386 if (atlyxpreamble.find(from_ascii("@")) != docstring::npos)
1387 lyxpreamble += "\n\\makeatletter\n"
1388 + atlyxpreamble + "\\makeatother\n\n";
1390 lyxpreamble += '\n' + atlyxpreamble;
1392 // We try to load babel late, in case it interferes with other packages.
1393 // Jurabib and Hyperref have to be called after babel, though.
1394 if (use_babel && !features.isRequired("jurabib")
1395 && !features.isRequired("hyperref")
1396 && !features.isRequired("vietnamese")
1397 && !features.isRequired("japanese")) {
1399 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1400 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1404 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1405 for (int j = 0; j != nlines; ++j) {
1414 void BufferParams::useClassDefaults()
1416 DocumentClass const & tclass = documentClass();
1418 sides = tclass.sides();
1419 columns = tclass.columns();
1420 pagestyle = tclass.pagestyle();
1421 options = tclass.options();
1422 // Only if class has a ToC hierarchy
1423 if (tclass.hasTocLevels()) {
1424 secnumdepth = tclass.secnumdepth();
1425 tocdepth = tclass.tocdepth();
1430 bool BufferParams::hasClassDefaults() const
1432 DocumentClass const & tclass = documentClass();
1434 return sides == tclass.sides()
1435 && columns == tclass.columns()
1436 && pagestyle == tclass.pagestyle()
1437 && options == tclass.options()
1438 && secnumdepth == tclass.secnumdepth()
1439 && tocdepth == tclass.tocdepth();
1443 DocumentClass const & BufferParams::documentClass() const
1449 DocumentClass const * BufferParams::documentClassPtr() const {
1454 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1455 // evil, but this function is evil
1456 doc_class_ = const_cast<DocumentClass *>(tc);
1460 bool BufferParams::setBaseClass(string const & classname)
1462 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1463 LayoutFileList & bcl = LayoutFileList::get();
1464 if (!bcl.haveClass(classname)) {
1466 bformat(_("The document class %1$s could not be found. "
1467 "A default textclass with default layouts will be used. "
1468 "LyX might not be able to produce output unless a correct "
1469 "textclass is selected from the document settings dialog."),
1470 from_utf8(classname));
1471 frontend::Alert::error(_("Document class not found"), s);
1472 bcl.addEmptyClass(classname);
1475 bool const success = bcl[classname].load();
1478 bformat(_("The document class %1$s could not be loaded."),
1479 from_utf8(classname));
1480 frontend::Alert::error(_("Could not load class"), s);
1484 pimpl_->baseClass_ = classname;
1486 // add any required modules not already in use
1487 list<string> const & mods = baseClass()->defaultModules();
1488 list<string>::const_iterator mit = mods.begin();
1489 list<string>::const_iterator men = mods.end();
1490 for (; mit != men; mit++) {
1491 string const & modName = *mit;
1492 // see if we're already in use
1493 if (find(layoutModules_.begin(), layoutModules_.end(), modName) !=
1494 layoutModules_.end()) {
1495 LYXERR(Debug::TCLASS, "Default module `" << modName <<
1496 "' not added because already used.");
1499 // make sure the user hasn't removed it
1500 if (find(removedModules_.begin(), removedModules_.end(), modName) !=
1501 removedModules_.end()) {
1502 LYXERR(Debug::TCLASS, "Default module `" << modName <<
1503 "' not added because removed by user.");
1506 // Now we want to check the list of selected modules to see if any of them
1507 // exclude this one.
1508 bool foundit = false;
1509 // so iterate over the selected modules...
1510 LayoutModuleList::const_iterator lit = layoutModules_.begin();
1511 LayoutModuleList::const_iterator len = layoutModules_.end();
1512 for (; lit != len; lit++) {
1513 LyXModule * lm = moduleList[*lit];
1516 vector<string> const & exc = lm->getExcludedModules();
1517 // ...and see if this one excludes us.
1518 if (find(exc.begin(), exc.end(), modName) != exc.end()) {
1520 LYXERR(Debug::TCLASS, "Default module `" << modName <<
1521 "' not added because excluded by loaded module `" <<
1527 LYXERR(Debug::TCLASS, "Default module `" << modName << "' added.");
1528 layoutModules_.push_back(modName);
1535 LayoutFile const * BufferParams::baseClass() const
1537 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1538 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1544 LayoutFileIndex const & BufferParams::baseClassID() const
1546 return pimpl_->baseClass_;
1550 void BufferParams::makeDocumentClass()
1555 doc_class_ = &(DocumentClassBundle::get().newClass(*baseClass()));
1557 // FIXME It might be worth loading the children's modules here,
1558 // just as we load their bibliographies and such, instead of just
1559 // doing a check in InsetInclude.
1560 LayoutModuleList::const_iterator it = layoutModules_.begin();
1561 for (; it != layoutModules_.end(); it++) {
1562 string const modName = *it;
1563 LyXModule * lm = moduleList[modName];
1565 docstring const msg =
1566 bformat(_("The module %1$s has been requested by\n"
1567 "this document but has not been found in the list of\n"
1568 "available modules. If you recently installed it, you\n"
1569 "probably need to reconfigure LyX.\n"), from_utf8(modName));
1570 frontend::Alert::warning(_("Module not available"),
1571 msg + _("Some layouts may not be available."));
1572 LYXERR0("BufferParams::makeDocumentClass(): Module " <<
1573 modName << " requested but not found in module list.");
1576 if (!lm->isAvailable()) {
1577 docstring const msg =
1578 bformat(_("The module %1$s requires a package that is\n"
1579 "not available in your LaTeX installation. LaTeX output\n"
1580 "may not be possible.\n"), from_utf8(modName));
1581 frontend::Alert::warning(_("Package not available"), msg);
1583 FileName layout_file = libFileSearch("layouts", lm->getFilename());
1584 if (!doc_class_->read(layout_file, TextClass::MODULE)) {
1585 docstring const msg =
1586 bformat(_("Error reading module %1$s\n"), from_utf8(modName));
1587 frontend::Alert::warning(_("Read Error"), msg);
1590 if (!local_layout.empty()) {
1591 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1592 docstring const msg = _("Error reading internal layout information");
1593 frontend::Alert::warning(_("Read Error"), msg);
1599 bool BufferParams::addLayoutModule(string const & modName)
1601 LayoutModuleList::const_iterator it = layoutModules_.begin();
1602 LayoutModuleList::const_iterator end = layoutModules_.end();
1603 for (; it != end; it++)
1606 layoutModules_.push_back(modName);
1611 Font const BufferParams::getFont() const
1613 FontInfo f = documentClass().defaultfont();
1614 if (fontsDefaultFamily == "rmdefault")
1615 f.setFamily(ROMAN_FAMILY);
1616 else if (fontsDefaultFamily == "sfdefault")
1617 f.setFamily(SANS_FAMILY);
1618 else if (fontsDefaultFamily == "ttdefault")
1619 f.setFamily(TYPEWRITER_FAMILY);
1620 return Font(f, language);
1624 void BufferParams::readPreamble(Lexer & lex)
1626 if (lex.getString() != "\\begin_preamble")
1627 lyxerr << "Error (BufferParams::readPreamble):"
1628 "consistency check failed." << endl;
1630 preamble = lex.getLongString("\\end_preamble");
1634 void BufferParams::readLocalLayout(Lexer & lex)
1636 if (lex.getString() != "\\begin_local_layout")
1637 lyxerr << "Error (BufferParams::readLocalLayout):"
1638 "consistency check failed." << endl;
1640 local_layout = lex.getLongString("\\end_local_layout");
1644 void BufferParams::readLanguage(Lexer & lex)
1646 if (!lex.next()) return;
1648 string const tmptok = lex.getString();
1650 // check if tmptok is part of tex_babel in tex-defs.h
1651 language = languages.getLanguage(tmptok);
1653 // Language tmptok was not found
1654 language = default_language;
1655 lyxerr << "Warning: Setting language `"
1656 << tmptok << "' to `" << language->lang()
1662 void BufferParams::readGraphicsDriver(Lexer & lex)
1667 string const tmptok = lex.getString();
1668 // check if tmptok is part of tex_graphics in tex_defs.h
1671 string const test = tex_graphics[n++];
1673 if (test == tmptok) {
1674 graphicsDriver = tmptok;
1679 "Warning: graphics driver `$$Token' not recognized!\n"
1680 " Setting graphics driver to `default'.\n");
1681 graphicsDriver = "default";
1688 void BufferParams::readBullets(Lexer & lex)
1693 int const index = lex.getInteger();
1695 int temp_int = lex.getInteger();
1696 user_defined_bullet(index).setFont(temp_int);
1697 temp_bullet(index).setFont(temp_int);
1699 user_defined_bullet(index).setCharacter(temp_int);
1700 temp_bullet(index).setCharacter(temp_int);
1702 user_defined_bullet(index).setSize(temp_int);
1703 temp_bullet(index).setSize(temp_int);
1707 void BufferParams::readBulletsLaTeX(Lexer & lex)
1709 // The bullet class should be able to read this.
1712 int const index = lex.getInteger();
1714 docstring const temp_str = lex.getDocString();
1716 user_defined_bullet(index).setText(temp_str);
1717 temp_bullet(index).setText(temp_str);
1721 void BufferParams::readModules(Lexer & lex)
1723 if (!lex.eatLine()) {
1724 lyxerr << "Error (BufferParams::readModules):"
1725 "Unexpected end of input." << endl;
1729 string mod = lex.getString();
1730 if (mod == "\\end_modules")
1732 addLayoutModule(mod);
1738 void BufferParams::readRemovedModules(Lexer & lex)
1740 if (!lex.eatLine()) {
1741 lyxerr << "Error (BufferParams::readRemovedModules):"
1742 "Unexpected end of input." << endl;
1746 string mod = lex.getString();
1747 if (mod == "\\end_removed_modules")
1749 removedModules_.insert(mod);
1752 // now we want to remove any removed modules that were previously
1753 // added. normally, that will be because default modules were added in
1754 // setBaseClass(), which gets called when \textclass is read at the
1755 // start of the read.
1756 set<string>::const_iterator rit = removedModules_.begin();
1757 set<string>::const_iterator const ren = removedModules_.end();
1758 for (; rit != ren; rit++) {
1759 LayoutModuleList::iterator const mit = layoutModules_.begin();
1760 LayoutModuleList::iterator const men = layoutModules_.end();
1761 LayoutModuleList::iterator found = find(mit, men, *rit);
1764 layoutModules_.erase(found);
1769 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1771 char real_papersize = papersize;
1772 if (real_papersize == PAPER_DEFAULT)
1773 real_papersize = lyxrc.default_papersize;
1775 switch (real_papersize) {
1777 // could be anything, so don't guess
1779 case PAPER_CUSTOM: {
1780 if (purpose == XDVI && !paperwidth.empty() &&
1781 !paperheight.empty()) {
1782 // heightxwidth<unit>
1783 string first = paperwidth;
1784 string second = paperheight;
1785 if (orientation == ORIENTATION_LANDSCAPE)
1788 return first.erase(first.length() - 2)
1800 // dvips and dvipdfm do not know this
1801 if (purpose == DVIPS || purpose == DVIPDFM)
1805 // dvipdfm does not know this
1806 if (purpose == DVIPDFM)
1810 // dvipdfm does not know this
1811 if (purpose == DVIPDFM)
1814 case PAPER_USEXECUTIVE:
1815 // dvipdfm does not know this
1816 if (purpose == DVIPDFM)
1821 case PAPER_USLETTER:
1823 if (purpose == XDVI)
1830 string const BufferParams::dvips_options() const
1835 && papersize == PAPER_CUSTOM
1836 && !lyxrc.print_paper_dimension_flag.empty()
1837 && !paperwidth.empty()
1838 && !paperheight.empty()) {
1839 // using a custom papersize
1840 result = lyxrc.print_paper_dimension_flag;
1841 result += ' ' + paperwidth;
1842 result += ',' + paperheight;
1844 string const paper_option = paperSizeName(DVIPS);
1845 if (!paper_option.empty() && (paper_option != "letter" ||
1846 orientation != ORIENTATION_LANDSCAPE)) {
1847 // dvips won't accept -t letter -t landscape.
1848 // In all other cases, include the paper size
1850 result = lyxrc.print_paper_flag;
1851 result += ' ' + paper_option;
1854 if (orientation == ORIENTATION_LANDSCAPE &&
1855 papersize != PAPER_CUSTOM)
1856 result += ' ' + lyxrc.print_landscape_flag;
1861 string BufferParams::babelCall(string const & lang_opts) const
1863 string lang_pack = lyxrc.language_package;
1864 if (lang_pack != "\\usepackage{babel}")
1866 // suppress the babel call when there is no babel language defined
1867 // for the document language in the lib/languages file and if no
1868 // other languages are used (lang_opts is then empty)
1869 if (lang_opts.empty())
1871 // If Vietnamese is used, babel must directly be loaded with the
1872 // language options, see
1873 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1874 size_t viet = lang_opts.find("vietnam");
1875 // viet = string::npos when not found
1876 // the same is for all other languages that are not directly supported by
1877 // babel, but where LaTeX-packages add babel support.
1878 // this is currently the case for Latvian, Lithuanian, and Mongolian
1879 size_t latvian = lang_opts.find("latvian");
1880 size_t lithu = lang_opts.find("lithuanian");
1881 size_t mongo = lang_opts.find("mongolian");
1882 // If Japanese is used, babel must directly be loaded with the
1883 // language options, see
1884 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1885 size_t japan = lang_opts.find("japanese");
1886 if (!lyxrc.language_global_options || viet != string::npos
1887 || japan != string::npos || latvian != string::npos
1888 || lithu != string::npos || mongo != string::npos)
1889 return "\\usepackage[" + lang_opts + "]{babel}";
1894 void BufferParams::writeEncodingPreamble(odocstream & os,
1895 LaTeXFeatures & features, TexRow & texrow) const
1897 if (inputenc == "auto") {
1898 string const doc_encoding =
1899 language->encoding()->latexName();
1900 Encoding::Package const package =
1901 language->encoding()->package();
1903 // Create a list with all the input encodings used
1905 set<string> encodings =
1906 features.getEncodingSet(doc_encoding);
1908 // If the "japanese" package (i.e. pLaTeX) is used,
1909 // inputenc must be omitted.
1910 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1911 if (package == Encoding::japanese)
1912 features.require("japanese");
1914 if ((!encodings.empty() || package == Encoding::inputenc)
1915 && !features.isRequired("japanese")) {
1916 os << "\\usepackage[";
1917 set<string>::const_iterator it = encodings.begin();
1918 set<string>::const_iterator const end = encodings.end();
1920 os << from_ascii(*it);
1923 for (; it != end; ++it)
1924 os << ',' << from_ascii(*it);
1925 if (package == Encoding::inputenc) {
1926 if (!encodings.empty())
1928 os << from_ascii(doc_encoding);
1930 os << "]{inputenc}\n";
1933 if (package == Encoding::CJK || features.mustProvide("CJK")) {
1934 os << "\\usepackage{CJK}\n";
1937 } else if (inputenc != "default") {
1938 switch (encoding().package()) {
1939 case Encoding::none:
1940 case Encoding::japanese:
1942 case Encoding::inputenc:
1943 // do not load inputenc if japanese is used
1944 if (features.isRequired("japanese"))
1946 os << "\\usepackage[" << from_ascii(inputenc)
1951 os << "\\usepackage{CJK}\n";
1957 // The encoding "armscii8" (for Armenian) is only available when
1958 // the package "armtex" is loaded.
1959 if (language->encoding()->latexName() == "armscii8"
1960 || inputenc == "armscii8") {
1961 os << "\\usepackage{armtex}\n";
1967 string const BufferParams::loadFonts(string const & rm,
1968 string const & sf, string const & tt,
1969 bool const & sc, bool const & osf,
1970 int const & sfscale, int const & ttscale) const
1972 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1973 several packages have been replaced by others, that might not
1974 be installed on every system. We have to take care for that
1975 (see psnfss.pdf). We try to support all psnfss fonts as well
1976 as the fonts that have become de facto standard in the LaTeX
1977 world (e.g. Latin Modern). We do not support obsolete fonts
1978 (like PSLatex). In general, it should be possible to mix any
1979 rm font with any sf or tt font, respectively. (JSpitzm)
1981 -- separate math fonts.
1984 if (rm == "default" && sf == "default" && tt == "default")
1991 // Computer Modern (must be explicitely selectable -- there might be classes
1992 // that define a different default font!
1994 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1995 // osf for Computer Modern needs eco.sty
1997 os << "\\usepackage{eco}\n";
1999 // Latin Modern Roman
2000 else if (rm == "lmodern")
2001 os << "\\usepackage{lmodern}\n";
2003 else if (rm == "ae") {
2004 // not needed when using OT1 font encoding.
2005 if (lyxrc.fontenc != "default")
2006 os << "\\usepackage{ae,aecompl}\n";
2009 else if (rm == "times") {
2010 // try to load the best available package
2011 if (LaTeXFeatures::isAvailable("mathptmx"))
2012 os << "\\usepackage{mathptmx}\n";
2013 else if (LaTeXFeatures::isAvailable("mathptm"))
2014 os << "\\usepackage{mathptm}\n";
2016 os << "\\usepackage{times}\n";
2019 else if (rm == "palatino") {
2020 // try to load the best available package
2021 if (LaTeXFeatures::isAvailable("mathpazo")) {
2022 os << "\\usepackage";
2028 // "osf" includes "sc"!
2032 os << "{mathpazo}\n";
2034 else if (LaTeXFeatures::isAvailable("mathpple"))
2035 os << "\\usepackage{mathpple}\n";
2037 os << "\\usepackage{palatino}\n";
2040 else if (rm == "utopia") {
2041 // fourier supersedes utopia.sty, but does
2042 // not work with OT1 encoding.
2043 if (LaTeXFeatures::isAvailable("fourier")
2044 && lyxrc.fontenc != "default") {
2045 os << "\\usepackage";
2056 os << "{fourier}\n";
2059 os << "\\usepackage{utopia}\n";
2061 // Bera (complete fontset)
2062 else if (rm == "bera" && sf == "default" && tt == "default")
2063 os << "\\usepackage{bera}\n";
2065 else if (rm != "default")
2066 os << "\\usepackage" << "{" << rm << "}\n";
2069 // Helvetica, Bera Sans
2070 if (sf == "helvet" || sf == "berasans") {
2072 os << "\\usepackage[scaled=" << float(sfscale) / 100
2073 << "]{" << sf << "}\n";
2075 os << "\\usepackage{" << sf << "}\n";
2078 else if (sf == "avant")
2079 os << "\\usepackage{" << sf << "}\n";
2080 // Computer Modern, Latin Modern, CM Bright
2081 else if (sf != "default")
2082 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2084 // monospaced/typewriter
2085 // Courier, LuxiMono
2086 if (tt == "luximono" || tt == "beramono") {
2088 os << "\\usepackage[scaled=" << float(ttscale) / 100
2089 << "]{" << tt << "}\n";
2091 os << "\\usepackage{" << tt << "}\n";
2094 else if (tt == "courier" )
2095 os << "\\usepackage{" << tt << "}\n";
2096 // Computer Modern, Latin Modern, CM Bright
2097 else if (tt != "default")
2098 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2104 Encoding const & BufferParams::encoding() const
2106 if (inputenc == "auto" || inputenc == "default")
2107 return *language->encoding();
2108 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2111 LYXERR0("Unknown inputenc value `" << inputenc
2112 << "'. Using `auto' instead.");
2113 return *language->encoding();
2117 CiteEngine BufferParams::citeEngine() const
2119 // FIXME the class should provide the numerical/
2120 // authoryear choice
2121 if (documentClass().provides("natbib")
2122 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2123 return ENGINE_NATBIB_AUTHORYEAR;
2124 return cite_engine_;
2128 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2130 cite_engine_ = cite_engine;