2 * \file BufferParams.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alfredo Braunstein
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
11 * \author Martin Vermeer
13 * Full author contact details are available in file CREDITS.
18 #include "BufferParams.h"
21 #include "LayoutFile.h"
22 #include "BranchList.h"
23 #include "buffer_funcs.h"
29 #include "LaTeXFeatures.h"
30 #include "ModuleList.h"
34 #include "OutputParams.h"
38 #include "PDFOptions.h"
40 #include "frontends/alert.h"
42 #include "insets/InsetListingsParams.h"
44 #include "support/convert.h"
45 #include "support/debug.h"
46 #include "support/docstream.h"
47 #include "support/FileName.h"
48 #include "support/filetools.h"
49 #include "support/gettext.h"
50 #include "support/Messages.h"
51 #include "support/Translator.h"
52 #include "support/lstrings.h"
58 using namespace lyx::support;
61 static char const * const string_paragraph_separation[] = {
66 static char const * const string_quotes_language[] = {
67 "english", "swedish", "german", "polish", "french", "danish", ""
71 static char const * const string_papersize[] = {
72 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
73 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
77 static char const * const string_orientation[] = {
78 "portrait", "landscape", ""
82 static char const * const string_footnotekinds[] = {
83 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
87 static char const * const tex_graphics[] = {
88 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
89 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
90 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
91 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
102 // Paragraph separation
103 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
106 ParSepTranslator const init_parseptranslator()
108 ParSepTranslator translator
109 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
110 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
115 ParSepTranslator const & parseptranslator()
117 static ParSepTranslator translator = init_parseptranslator();
123 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
126 QuotesLangTranslator const init_quoteslangtranslator()
128 QuotesLangTranslator translator
129 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
130 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
131 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
132 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
133 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
134 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
139 QuotesLangTranslator const & quoteslangtranslator()
141 static QuotesLangTranslator translator = init_quoteslangtranslator();
147 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
150 static PaperSizeTranslator initPaperSizeTranslator()
152 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
153 translator.addPair(string_papersize[1], PAPER_CUSTOM);
154 translator.addPair(string_papersize[2], PAPER_USLETTER);
155 translator.addPair(string_papersize[3], PAPER_USLEGAL);
156 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
157 translator.addPair(string_papersize[5], PAPER_A3);
158 translator.addPair(string_papersize[6], PAPER_A4);
159 translator.addPair(string_papersize[7], PAPER_A5);
160 translator.addPair(string_papersize[8], PAPER_B3);
161 translator.addPair(string_papersize[9], PAPER_B4);
162 translator.addPair(string_papersize[10], PAPER_B5);
167 PaperSizeTranslator const & papersizetranslator()
169 static PaperSizeTranslator translator = initPaperSizeTranslator();
175 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
178 PaperOrientationTranslator const init_paperorientationtranslator()
180 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
181 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
186 PaperOrientationTranslator const & paperorientationtranslator()
188 static PaperOrientationTranslator translator = init_paperorientationtranslator();
194 typedef Translator<int, PageSides> SidesTranslator;
197 SidesTranslator const init_sidestranslator()
199 SidesTranslator translator(1, OneSide);
200 translator.addPair(2, TwoSides);
205 SidesTranslator const & sidestranslator()
207 static SidesTranslator translator = init_sidestranslator();
213 typedef Translator<int, BufferParams::Package> PackageTranslator;
216 PackageTranslator const init_packagetranslator()
218 PackageTranslator translator(0, BufferParams::package_off);
219 translator.addPair(1, BufferParams::package_auto);
220 translator.addPair(2, BufferParams::package_on);
225 PackageTranslator const & packagetranslator()
227 static PackageTranslator translator = init_packagetranslator();
233 typedef Translator<string, CiteEngine> CiteEngineTranslator;
236 CiteEngineTranslator const init_citeenginetranslator()
238 CiteEngineTranslator translator("basic", ENGINE_BASIC);
239 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
240 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
241 translator.addPair("jurabib", ENGINE_JURABIB);
246 CiteEngineTranslator const & citeenginetranslator()
248 static CiteEngineTranslator translator = init_citeenginetranslator();
254 typedef Translator<string, Spacing::Space> SpaceTranslator;
257 SpaceTranslator const init_spacetranslator()
259 SpaceTranslator translator("default", Spacing::Default);
260 translator.addPair("single", Spacing::Single);
261 translator.addPair("onehalf", Spacing::Onehalf);
262 translator.addPair("double", Spacing::Double);
263 translator.addPair("other", Spacing::Other);
268 SpaceTranslator const & spacetranslator()
270 static SpaceTranslator translator = init_spacetranslator();
277 class BufferParams::Impl
282 AuthorList authorlist;
283 BranchList branchlist;
284 Bullet temp_bullets[4];
285 Bullet user_defined_bullets[4];
287 /** This is the amount of space used for paragraph_separation "skip",
288 * and for detached paragraphs in "indented" documents.
291 PDFOptions pdfoptions;
292 LayoutFileIndex baseClass_;
296 BufferParams::Impl::Impl()
297 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
299 // set initial author
301 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
306 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
310 return new BufferParams::Impl(*ptr);
314 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
320 BufferParams::BufferParams()
323 setBaseClass(defaultBaseclass());
325 paragraph_separation = ParagraphIndentSeparation;
326 quotes_language = InsetQuotes::EnglishQuotes;
327 fontsize = "default";
330 papersize = PAPER_DEFAULT;
331 orientation = ORIENTATION_PORTRAIT;
332 use_geometry = false;
333 use_amsmath = package_auto;
334 use_esint = package_auto;
335 cite_engine_ = ENGINE_BASIC;
336 use_bibtopic = false;
337 trackChanges = false;
338 outputChanges = false;
339 use_default_options = true;
342 language = default_language;
343 fontsRoman = "default";
344 fontsSans = "default";
345 fontsTypewriter = "default";
346 fontsDefaultFamily = "default";
350 fontsSansScale = 100;
351 fontsTypewriterScale = 100;
353 graphicsDriver = "default";
354 defaultOutputFormat = "default";
357 listings_params = string();
358 pagestyle = "default";
359 // white is equal to no background color
360 backgroundcolor = lyx::rgbFromHexName("#ffffff");
362 for (int iter = 0; iter < 4; ++iter) {
363 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
364 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
369 docstring BufferParams::B_(string const & l10n) const
371 LASSERT(language, /**/);
372 return getMessages(language->code()).get(l10n);
376 AuthorList & BufferParams::authors()
378 return pimpl_->authorlist;
382 AuthorList const & BufferParams::authors() const
384 return pimpl_->authorlist;
388 BranchList & BufferParams::branchlist()
390 return pimpl_->branchlist;
394 BranchList const & BufferParams::branchlist() const
396 return pimpl_->branchlist;
400 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
402 LASSERT(index < 4, /**/);
403 return pimpl_->temp_bullets[index];
407 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
409 LASSERT(index < 4, /**/);
410 return pimpl_->temp_bullets[index];
414 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
416 LASSERT(index < 4, /**/);
417 return pimpl_->user_defined_bullets[index];
421 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
423 LASSERT(index < 4, /**/);
424 return pimpl_->user_defined_bullets[index];
428 Spacing & BufferParams::spacing()
430 return pimpl_->spacing;
434 Spacing const & BufferParams::spacing() const
436 return pimpl_->spacing;
440 PDFOptions & BufferParams::pdfoptions()
442 return pimpl_->pdfoptions;
446 PDFOptions const & BufferParams::pdfoptions() const
448 return pimpl_->pdfoptions;
452 VSpace const & BufferParams::getDefSkip() const
454 return pimpl_->defskip;
458 void BufferParams::setDefSkip(VSpace const & vs)
460 pimpl_->defskip = vs;
464 string BufferParams::readToken(Lexer & lex, string const & token,
465 FileName const & filepath)
467 if (token == "\\textclass") {
469 string const classname = lex.getString();
470 // if there exists a local layout file, ignore the system one
471 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
473 LayoutFileList & bcl = LayoutFileList::get();
474 if (tcp.empty() && !filepath.empty())
475 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
479 setBaseClass(classname);
480 // We assume that a tex class exists for local or unknown layouts so this warning
481 // will only be given for system layouts.
482 if (!baseClass()->isTeXClassAvailable()) {
483 docstring const msg =
484 bformat(_("The layout file requested by this document,\n"
486 "is not usable. This is probably because a LaTeX\n"
487 "class or style file required by it is not\n"
488 "available. See the Customization documentation\n"
489 "for more information.\n"), from_utf8(classname));
490 frontend::Alert::warning(_("Document class not available"),
491 msg + _("LyX will not be able to produce output."));
493 } else if (token == "\\begin_preamble") {
495 } else if (token == "\\begin_local_layout") {
496 readLocalLayout(lex);
497 } else if (token == "\\begin_modules") {
499 } else if (token == "\\begin_removed_modules") {
500 readRemovedModules(lex);
501 } else if (token == "\\options") {
503 options = lex.getString();
504 } else if (token == "\\use_default_options") {
505 lex >> use_default_options;
506 } else if (token == "\\master") {
508 master = lex.getString();
509 } else if (token == "\\language") {
511 } else if (token == "\\inputencoding") {
513 } else if (token == "\\graphics") {
514 readGraphicsDriver(lex);
515 } else if (token == "\\default_output_format") {
516 lex >> defaultOutputFormat;
517 } else if (token == "\\font_roman") {
519 fontsRoman = lex.getString();
520 } else if (token == "\\font_sans") {
522 fontsSans = lex.getString();
523 } else if (token == "\\font_typewriter") {
525 fontsTypewriter = lex.getString();
526 } else if (token == "\\font_default_family") {
527 lex >> fontsDefaultFamily;
528 } else if (token == "\\use_xetex") {
530 } else if (token == "\\font_sc") {
532 } else if (token == "\\font_osf") {
534 } else if (token == "\\font_sf_scale") {
535 lex >> fontsSansScale;
536 } else if (token == "\\font_tt_scale") {
537 lex >> fontsTypewriterScale;
538 } else if (token == "\\font_cjk") {
540 } else if (token == "\\paragraph_separation") {
543 paragraph_separation = parseptranslator().find(parsep);
544 } else if (token == "\\defskip") {
546 string defskip = lex.getString();
547 if (defskip == "defskip")
550 pimpl_->defskip = VSpace(defskip);
551 } else if (token == "\\quotes_language") {
554 quotes_language = quoteslangtranslator().find(quotes_lang);
555 } else if (token == "\\papersize") {
558 papersize = papersizetranslator().find(ppsize);
559 } else if (token == "\\use_geometry") {
561 } else if (token == "\\use_amsmath") {
564 use_amsmath = packagetranslator().find(use_ams);
565 } else if (token == "\\use_esint") {
568 use_esint = packagetranslator().find(useesint);
569 } else if (token == "\\cite_engine") {
572 cite_engine_ = citeenginetranslator().find(engine);
573 } else if (token == "\\use_bibtopic") {
575 } else if (token == "\\tracking_changes") {
577 } else if (token == "\\output_changes") {
578 lex >> outputChanges;
579 } else if (token == "\\branch") {
581 docstring branch = lex.getDocString();
582 branchlist().add(branch);
585 string const tok = lex.getString();
586 if (tok == "\\end_branch")
588 Branch * branch_ptr = branchlist().find(branch);
589 if (tok == "\\selected") {
592 branch_ptr->setSelected(lex.getInteger());
594 // not yet operational
595 if (tok == "\\color") {
597 string color = lex.getString();
599 branch_ptr->setColor(color);
600 // Update also the Color table:
602 color = lcolor.getX11Name(Color_background);
604 lcolor.setColor(to_utf8(branch), color);
607 } else if (token == "\\author") {
609 istringstream ss(lex.getString());
612 author_map.push_back(pimpl_->authorlist.record(a));
613 } else if (token == "\\paperorientation") {
616 orientation = paperorientationtranslator().find(orient);
617 } else if (token == "\\backgroundcolor") {
619 backgroundcolor = lyx::rgbFromHexName(lex.getString());
620 } else if (token == "\\paperwidth") {
622 } else if (token == "\\paperheight") {
624 } else if (token == "\\leftmargin") {
626 } else if (token == "\\topmargin") {
628 } else if (token == "\\rightmargin") {
630 } else if (token == "\\bottommargin") {
632 } else if (token == "\\headheight") {
634 } else if (token == "\\headsep") {
636 } else if (token == "\\footskip") {
638 } else if (token == "\\columnsep") {
640 } else if (token == "\\paperfontsize") {
642 } else if (token == "\\papercolumns") {
644 } else if (token == "\\listings_params") {
647 listings_params = InsetListingsParams(par).params();
648 } else if (token == "\\papersides") {
651 sides = sidestranslator().find(psides);
652 } else if (token == "\\paperpagestyle") {
654 } else if (token == "\\bullet") {
656 } else if (token == "\\bulletLaTeX") {
657 readBulletsLaTeX(lex);
658 } else if (token == "\\secnumdepth") {
660 } else if (token == "\\tocdepth") {
662 } else if (token == "\\spacing") {
666 if (nspacing == "other") {
669 spacing().set(spacetranslator().find(nspacing), tmp_val);
670 } else if (token == "\\float_placement") {
671 lex >> float_placement;
673 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
674 string toktmp = pdfoptions().readToken(lex, token);
675 if (!toktmp.empty()) {
676 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
681 lyxerr << "BufferParams::readToken(): Unknown token: " <<
690 void BufferParams::writeFile(ostream & os) const
692 // The top of the file is written by the buffer.
693 // Prints out the buffer info into the .lyx file given by file
696 os << "\\textclass " << baseClass()->name() << '\n';
699 if (!preamble.empty()) {
700 // remove '\n' from the end of preamble
701 string const tmppreamble = rtrim(preamble, "\n");
702 os << "\\begin_preamble\n"
704 << "\n\\end_preamble\n";
708 if (!options.empty()) {
709 os << "\\options " << options << '\n';
712 // use the class options defined in the layout?
713 os << "\\use_default_options "
714 << convert<string>(use_default_options) << "\n";
716 // the master document
717 if (!master.empty()) {
718 os << "\\master " << master << '\n';
722 if (!removedModules_.empty()) {
723 os << "\\begin_removed_modules" << '\n';
724 list<string>::const_iterator it = removedModules_.begin();
725 list<string>::const_iterator en = removedModules_.end();
726 for (; it != en; it++)
728 os << "\\end_removed_modules" << '\n';
732 if (!layoutModules_.empty()) {
733 os << "\\begin_modules" << '\n';
734 LayoutModuleList::const_iterator it = layoutModules_.begin();
735 LayoutModuleList::const_iterator en = layoutModules_.end();
736 for (; it != en; it++)
738 os << "\\end_modules" << '\n';
741 // local layout information
742 if (!local_layout.empty()) {
743 // remove '\n' from the end
744 string const tmplocal = rtrim(local_layout, "\n");
745 os << "\\begin_local_layout\n"
747 << "\n\\end_local_layout\n";
750 // then the text parameters
751 if (language != ignore_language)
752 os << "\\language " << language->lang() << '\n';
753 os << "\\inputencoding " << inputenc
754 << "\n\\font_roman " << fontsRoman
755 << "\n\\font_sans " << fontsSans
756 << "\n\\font_typewriter " << fontsTypewriter
757 << "\n\\font_default_family " << fontsDefaultFamily
758 << "\n\\use_xetex " << convert<string>(useXetex)
759 << "\n\\font_sc " << convert<string>(fontsSC)
760 << "\n\\font_osf " << convert<string>(fontsOSF)
761 << "\n\\font_sf_scale " << fontsSansScale
762 << "\n\\font_tt_scale " << fontsTypewriterScale
764 if (!fontsCJK.empty()) {
765 os << "\\font_cjk " << fontsCJK << '\n';
767 os << "\n\\graphics " << graphicsDriver << '\n';
768 os << "\\default_output_format " << defaultOutputFormat << '\n';
770 if (!float_placement.empty()) {
771 os << "\\float_placement " << float_placement << '\n';
773 os << "\\paperfontsize " << fontsize << '\n';
775 spacing().writeFile(os);
776 pdfoptions().writeFile(os);
778 os << "\\papersize " << string_papersize[papersize]
779 << "\n\\use_geometry " << convert<string>(use_geometry)
780 << "\n\\use_amsmath " << use_amsmath
781 << "\n\\use_esint " << use_esint
782 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
783 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
784 << "\n\\paperorientation " << string_orientation[orientation]
785 << "\n\\backgroundcolor " << lyx::X11hexname(backgroundcolor)
788 BranchList::const_iterator it = branchlist().begin();
789 BranchList::const_iterator end = branchlist().end();
790 for (; it != end; ++it) {
791 os << "\\branch " << to_utf8(it->branch())
792 << "\n\\selected " << it->isSelected()
793 << "\n\\color " << lyx::X11hexname(it->color())
798 if (!paperwidth.empty())
799 os << "\\paperwidth "
800 << VSpace(paperwidth).asLyXCommand() << '\n';
801 if (!paperheight.empty())
802 os << "\\paperheight "
803 << VSpace(paperheight).asLyXCommand() << '\n';
804 if (!leftmargin.empty())
805 os << "\\leftmargin "
806 << VSpace(leftmargin).asLyXCommand() << '\n';
807 if (!topmargin.empty())
809 << VSpace(topmargin).asLyXCommand() << '\n';
810 if (!rightmargin.empty())
811 os << "\\rightmargin "
812 << VSpace(rightmargin).asLyXCommand() << '\n';
813 if (!bottommargin.empty())
814 os << "\\bottommargin "
815 << VSpace(bottommargin).asLyXCommand() << '\n';
816 if (!headheight.empty())
817 os << "\\headheight "
818 << VSpace(headheight).asLyXCommand() << '\n';
819 if (!headsep.empty())
821 << VSpace(headsep).asLyXCommand() << '\n';
822 if (!footskip.empty())
824 << VSpace(footskip).asLyXCommand() << '\n';
825 if (!columnsep.empty())
827 << VSpace(columnsep).asLyXCommand() << '\n';
828 os << "\\secnumdepth " << secnumdepth
829 << "\n\\tocdepth " << tocdepth
830 << "\n\\paragraph_separation "
831 << string_paragraph_separation[paragraph_separation]
832 << "\n\\defskip " << getDefSkip().asLyXCommand()
833 << "\n\\quotes_language "
834 << string_quotes_language[quotes_language]
835 << "\n\\papercolumns " << columns
836 << "\n\\papersides " << sides
837 << "\n\\paperpagestyle " << pagestyle << '\n';
838 if (!listings_params.empty())
839 os << "\\listings_params \"" <<
840 InsetListingsParams(listings_params).encodedString() << "\"\n";
841 for (int i = 0; i < 4; ++i) {
842 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
843 if (user_defined_bullet(i).getFont() != -1) {
844 os << "\\bullet " << i << " "
845 << user_defined_bullet(i).getFont() << " "
846 << user_defined_bullet(i).getCharacter() << " "
847 << user_defined_bullet(i).getSize() << "\n";
851 os << "\\bulletLaTeX " << i << " \""
852 << lyx::to_ascii(user_defined_bullet(i).getText())
858 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
859 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
861 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
862 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
863 for (; a_it != a_end; ++a_it) {
864 if (a_it->second.used())
865 os << "\\author " << a_it->second << "\n";
867 os << "\\author " << Author() << "\n";
872 void BufferParams::validate(LaTeXFeatures & features) const
874 features.require(documentClass().requires());
877 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
878 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
879 LaTeXFeatures::isAvailable("xcolor");
881 switch (features.runparams().flavor) {
882 case OutputParams::LATEX:
884 features.require("ct-dvipost");
885 features.require("dvipost");
886 } else if (xcolorulem) {
887 features.require("ct-xcolor-ulem");
888 features.require("ulem");
889 features.require("xcolor");
891 features.require("ct-none");
894 case OutputParams::PDFLATEX:
895 case OutputParams::XETEX:
897 features.require("ct-xcolor-ulem");
898 features.require("ulem");
899 features.require("xcolor");
900 // improves color handling in PDF output
901 features.require("pdfcolmk");
903 features.require("ct-none");
911 // Floats with 'Here definitely' as default setting.
912 if (float_placement.find('H') != string::npos)
913 features.require("float");
915 // AMS Style is at document level
916 if (use_amsmath == package_on
917 || documentClass().provides("amsmath"))
918 features.require("amsmath");
919 if (use_esint == package_on)
920 features.require("esint");
922 // Document-level line spacing
923 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
924 features.require("setspace");
926 // the bullet shapes are buffer level not paragraph level
927 // so they are tested here
928 for (int i = 0; i < 4; ++i) {
929 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
931 int const font = user_defined_bullet(i).getFont();
933 int const c = user_defined_bullet(i).getCharacter();
939 features.require("latexsym");
941 } else if (font == 1) {
942 features.require("amssymb");
943 } else if (font >= 2 && font <= 5) {
944 features.require("pifont");
948 if (pdfoptions().use_hyperref) {
949 features.require("hyperref");
950 // due to interferences with babel and hyperref, the color package has to
951 // be loaded after hyperref when hyperref is used with the colorlinks
952 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
953 if (pdfoptions().colorlinks)
954 features.require("color");
958 features.require("xetex");
960 if (language->lang() == "vietnamese")
961 features.require("vietnamese");
962 else if (language->lang() == "japanese")
963 features.require("japanese");
967 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
968 TexRow & texrow) const
970 os << "\\documentclass";
972 DocumentClass const & tclass = documentClass();
974 ostringstream clsoptions; // the document class options.
976 if (tokenPos(tclass.opt_fontsize(),
977 '|', fontsize) >= 0) {
978 // only write if existing in list (and not default)
979 clsoptions << fontsize << "pt,";
982 // custom, A3, B3 and B4 paper sizes need geometry
983 bool nonstandard_papersize = papersize == PAPER_B3
984 || papersize == PAPER_B4
985 || papersize == PAPER_A3
986 || papersize == PAPER_CUSTOM;
991 clsoptions << "a4paper,";
994 clsoptions << "letterpaper,";
997 clsoptions << "a5paper,";
1000 clsoptions << "b5paper,";
1002 case PAPER_USEXECUTIVE:
1003 clsoptions << "executivepaper,";
1006 clsoptions << "legalpaper,";
1018 if (sides != tclass.sides()) {
1021 clsoptions << "oneside,";
1024 clsoptions << "twoside,";
1030 if (columns != tclass.columns()) {
1032 clsoptions << "twocolumn,";
1034 clsoptions << "onecolumn,";
1038 && orientation == ORIENTATION_LANDSCAPE)
1039 clsoptions << "landscape,";
1041 // language should be a parameter to \documentclass
1042 if (language->babel() == "hebrew"
1043 && default_language->babel() != "hebrew")
1044 // This seems necessary
1045 features.useLanguage(default_language);
1047 ostringstream language_options;
1048 bool const use_babel = features.useBabel();
1050 language_options << features.getLanguages();
1051 if (!language->babel().empty()) {
1052 if (!language_options.str().empty())
1053 language_options << ',';
1054 language_options << language->babel();
1056 // if Vietnamese is used, babel must directly be loaded
1057 // with language options, not in the class options, see
1058 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1059 size_t viet = language_options.str().find("vietnam");
1060 // viet = string::npos when not found
1061 // the same is for all other languages that are not directly supported by
1062 // babel, but where LaTeX-packages add babel support.
1063 // this is currently the case for Latvian, Lithuanian, and Mongolian
1064 size_t latvian = language_options.str().find("latvian");
1065 size_t lithu = language_options.str().find("lithuanian");
1066 size_t mongo = language_options.str().find("mongolian");
1067 // if Japanese is used, babel must directly be loaded
1068 // with language options, not in the class options, see
1069 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1070 size_t japan = language_options.str().find("japanese");
1071 if (lyxrc.language_global_options && !language_options.str().empty()
1072 && viet == string::npos && japan == string::npos
1073 && latvian == string::npos && lithu == string::npos
1074 && mongo == string::npos)
1075 clsoptions << language_options.str() << ',';
1078 // the predefined options from the layout
1079 if (use_default_options && !tclass.options().empty())
1080 clsoptions << tclass.options() << ',';
1082 // the user-defined options
1083 if (!options.empty()) {
1084 clsoptions << options << ',';
1087 string strOptions(clsoptions.str());
1088 if (!strOptions.empty()) {
1089 strOptions = rtrim(strOptions, ",");
1091 os << '[' << from_utf8(strOptions) << ']';
1094 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1096 // end of \documentclass defs
1099 os << "\\usepackage{fontspec}\n";
1103 // font selection must be done before loading fontenc.sty
1104 string const fonts =
1105 loadFonts(fontsRoman, fontsSans,
1106 fontsTypewriter, fontsSC, fontsOSF,
1107 fontsSansScale, fontsTypewriterScale, useXetex);
1108 if (!fonts.empty()) {
1109 os << from_ascii(fonts);
1112 if (fontsDefaultFamily != "default")
1113 os << "\\renewcommand{\\familydefault}{\\"
1114 << from_ascii(fontsDefaultFamily) << "}\n";
1116 // set font encoding
1117 // this one is not per buffer
1118 // for arabic_arabi and farsi we also need to load the LAE and
1120 // XeteX works without fontenc
1121 if (lyxrc.fontenc != "default" && language->lang() != "japanese"
1123 if (language->lang() == "arabic_arabi"
1124 || language->lang() == "farsi") {
1125 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1126 << ",LFE,LAE]{fontenc}\n";
1129 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1135 // handle inputenc etc.
1136 writeEncodingPreamble(os, features, texrow);
1138 if (!listings_params.empty() || features.isRequired("listings")) {
1139 os << "\\usepackage{listings}\n";
1142 if (!listings_params.empty()) {
1144 // do not test validity because listings_params is
1145 // supposed to be valid
1147 InsetListingsParams(listings_params).separatedParams(true);
1148 // we can't support all packages, but we should load the color package
1149 if (par.find("\\color", 0) != string::npos)
1150 features.require("color");
1151 os << from_utf8(par);
1152 // count the number of newlines
1153 for (size_t i = 0; i < par.size(); ++i)
1159 if (!tclass.provides("geometry")
1160 && (use_geometry || nonstandard_papersize)) {
1161 odocstringstream ods;
1162 if (!getGraphicsDriver("geometry").empty())
1163 ods << getGraphicsDriver("geometry");
1164 if (orientation == ORIENTATION_LANDSCAPE)
1165 ods << ",landscape";
1166 switch (papersize) {
1168 if (!paperwidth.empty())
1169 ods << ",paperwidth="
1170 << from_ascii(paperwidth);
1171 if (!paperheight.empty())
1172 ods << ",paperheight="
1173 << from_ascii(paperheight);
1175 case PAPER_USLETTER:
1176 ods << ",letterpaper";
1179 ods << ",legalpaper";
1181 case PAPER_USEXECUTIVE:
1182 ods << ",executivepaper";
1203 // default papersize ie PAPER_DEFAULT
1204 switch (lyxrc.default_papersize) {
1205 case PAPER_DEFAULT: // keep compiler happy
1206 case PAPER_USLETTER:
1207 ods << ",letterpaper";
1210 ods << ",legalpaper";
1212 case PAPER_USEXECUTIVE:
1213 ods << ",executivepaper";
1233 docstring const g_options = trim(ods.str(), ",");
1234 os << "\\usepackage";
1235 if (!g_options.empty())
1236 os << '[' << g_options << ']';
1237 os << "{geometry}\n";
1239 os << "\\geometry{verbose";
1240 if (!topmargin.empty())
1241 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1242 if (!bottommargin.empty())
1243 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1244 if (!leftmargin.empty())
1245 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1246 if (!rightmargin.empty())
1247 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1248 if (!headheight.empty())
1249 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1250 if (!headsep.empty())
1251 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1252 if (!footskip.empty())
1253 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1254 if (!columnsep.empty())
1255 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1258 } else if (orientation == ORIENTATION_LANDSCAPE) {
1259 features.require("papersize");
1262 if (tokenPos(tclass.opt_pagestyle(),
1263 '|', pagestyle) >= 0) {
1264 if (pagestyle == "fancy") {
1265 os << "\\usepackage{fancyhdr}\n";
1268 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1272 // only output when the background color is not white
1273 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1274 // only require color here, the background color will be defined
1275 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1277 features.require("color");
1278 features.require("pagecolor");
1281 // Only if class has a ToC hierarchy
1282 if (tclass.hasTocLevels()) {
1283 if (secnumdepth != tclass.secnumdepth()) {
1284 os << "\\setcounter{secnumdepth}{"
1289 if (tocdepth != tclass.tocdepth()) {
1290 os << "\\setcounter{tocdepth}{"
1297 if (paragraph_separation) {
1298 switch (getDefSkip().kind()) {
1299 case VSpace::SMALLSKIP:
1300 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1302 case VSpace::MEDSKIP:
1303 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1305 case VSpace::BIGSKIP:
1306 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1308 case VSpace::LENGTH:
1309 os << "\\setlength{\\parskip}{"
1310 << from_utf8(getDefSkip().length().asLatexString())
1313 default: // should never happen // Then delete it.
1314 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1319 os << "\\setlength{\\parindent}{0pt}\n";
1323 // Now insert the LyX specific LaTeX commands...
1324 docstring lyxpreamble;
1326 // due to interferences with babel and hyperref, the color package has to
1327 // be loaded (when it is not already loaded) before babel when hyperref
1328 // is used with the colorlinks option, see
1329 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1330 // we decided therefore to load color always before babel, see
1331 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1332 lyxpreamble += from_ascii(features.getColorOptions());
1334 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1336 && (features.isRequired("jurabib")
1337 || features.isRequired("hyperref")
1338 || features.isRequired("vietnamese")
1339 || features.isRequired("japanese") ) ) {
1341 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1342 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1345 // The optional packages;
1346 lyxpreamble += from_ascii(features.getPackages());
1349 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1352 // * Hyperref manual: "Make sure it comes last of your loaded
1353 // packages, to give it a fighting chance of not being over-written,
1354 // since its job is to redefine many LaTeX commands."
1355 // * Email from Heiko Oberdiek: "It is usually better to load babel
1356 // before hyperref. Then hyperref has a chance to detect babel.
1357 // * Has to be loaded before the "LyX specific LaTeX commands" to
1358 // avoid errors with algorithm floats.
1359 // use hyperref explicitely when it is required
1360 if (features.isRequired("hyperref")) {
1361 odocstringstream oss;
1362 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1363 lyxpreamble += oss.str();
1366 // Will be surrounded by \makeatletter and \makeatother when needed
1367 docstring atlyxpreamble;
1369 // Some macros LyX will need
1370 docstring tmppreamble(from_ascii(features.getMacros()));
1372 if (!tmppreamble.empty())
1373 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1374 "LyX specific LaTeX commands.\n"
1375 + tmppreamble + '\n';
1377 // the text class specific preamble
1378 tmppreamble = features.getTClassPreamble();
1379 if (!tmppreamble.empty())
1380 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1381 "Textclass specific LaTeX commands.\n"
1382 + tmppreamble + '\n';
1384 /* the user-defined preamble */
1385 if (!preamble.empty())
1387 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1388 "User specified LaTeX commands.\n"
1389 + from_utf8(preamble) + '\n';
1391 // subfig loads internally the LaTeX package "caption". As
1392 // caption is a very popular package, users will load it in
1393 // the preamble. Therefore we must load subfig behind the
1394 // user-defined preamble and check if the caption package was
1395 // loaded or not. For the case that caption is loaded before
1396 // subfig, there is the subfig option "caption=false". This
1397 // option also works when a koma-script class is used and
1398 // koma's own caption commands are used instead of caption. We
1399 // use \PassOptionsToPackage here because the user could have
1400 // already loaded subfig in the preamble.
1401 if (features.isRequired("subfig")) {
1402 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1403 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1404 "\\usepackage{subfig}\n";
1407 // Itemize bullet settings need to be last in case the user
1408 // defines their own bullets that use a package included
1409 // in the user-defined preamble -- ARRae
1410 // Actually it has to be done much later than that
1411 // since some packages like frenchb make modifications
1412 // at \begin{document} time -- JMarc
1413 docstring bullets_def;
1414 for (int i = 0; i < 4; ++i) {
1415 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1416 if (bullets_def.empty())
1417 bullets_def += "\\AtBeginDocument{\n";
1418 bullets_def += " \\def\\labelitemi";
1420 // `i' is one less than the item to modify
1427 bullets_def += "ii";
1433 bullets_def += '{' +
1434 user_defined_bullet(i).getText()
1439 if (!bullets_def.empty())
1440 atlyxpreamble += bullets_def + "}\n\n";
1442 if (atlyxpreamble.find(from_ascii("@")) != docstring::npos)
1443 lyxpreamble += "\n\\makeatletter\n"
1444 + atlyxpreamble + "\\makeatother\n\n";
1446 lyxpreamble += '\n' + atlyxpreamble;
1448 // We try to load babel late, in case it interferes with other packages.
1449 // Jurabib and Hyperref have to be called after babel, though.
1450 if (use_babel && !features.isRequired("jurabib")
1451 && !features.isRequired("hyperref")
1452 && !features.isRequired("vietnamese")
1453 && !features.isRequired("japanese")) {
1455 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1456 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1459 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1460 if (!i18npreamble.empty())
1461 lyxpreamble += i18npreamble + '\n';
1464 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1465 for (int j = 0; j != nlines; ++j) {
1471 // these packages (xunicode, for that matter) need to be loaded at least
1472 // after amsmath, amssymb, esint and the other packages that provide
1475 os << "\\usepackage{xunicode}\n";
1477 os << "\\usepackage{xltxtra}\n";
1484 void BufferParams::useClassDefaults()
1486 DocumentClass const & tclass = documentClass();
1488 sides = tclass.sides();
1489 columns = tclass.columns();
1490 pagestyle = tclass.pagestyle();
1491 use_default_options = true;
1492 // Only if class has a ToC hierarchy
1493 if (tclass.hasTocLevels()) {
1494 secnumdepth = tclass.secnumdepth();
1495 tocdepth = tclass.tocdepth();
1500 bool BufferParams::hasClassDefaults() const
1502 DocumentClass const & tclass = documentClass();
1504 return sides == tclass.sides()
1505 && columns == tclass.columns()
1506 && pagestyle == tclass.pagestyle()
1507 && use_default_options
1508 && secnumdepth == tclass.secnumdepth()
1509 && tocdepth == tclass.tocdepth();
1513 DocumentClass const & BufferParams::documentClass() const
1519 DocumentClass const * BufferParams::documentClassPtr() const {
1524 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1525 // evil, but this function is evil
1526 doc_class_ = const_cast<DocumentClass *>(tc);
1530 bool BufferParams::setBaseClass(string const & classname)
1532 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1533 LayoutFileList & bcl = LayoutFileList::get();
1534 if (!bcl.haveClass(classname)) {
1536 bformat(_("The document class %1$s could not be found. "
1537 "A default textclass with default layouts will be used. "
1538 "LyX might not be able to produce output unless a correct "
1539 "textclass is selected from the document settings dialog."),
1540 from_utf8(classname));
1541 frontend::Alert::error(_("Document class not found"), s);
1542 bcl.addEmptyClass(classname);
1545 bool const success = bcl[classname].load();
1548 bformat(_("The document class %1$s could not be loaded."),
1549 from_utf8(classname));
1550 frontend::Alert::error(_("Could not load class"), s);
1554 pimpl_->baseClass_ = classname;
1555 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1560 LayoutFile const * BufferParams::baseClass() const
1562 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1563 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1569 LayoutFileIndex const & BufferParams::baseClassID() const
1571 return pimpl_->baseClass_;
1575 void BufferParams::makeDocumentClass()
1580 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1582 if (!local_layout.empty()) {
1583 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1584 docstring const msg = _("Error reading internal layout information");
1585 frontend::Alert::warning(_("Read Error"), msg);
1590 bool BufferParams::moduleCanBeAdded(string const & modName) const
1592 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1596 bool BufferParams::addLayoutModule(string const & modName)
1598 LayoutModuleList::const_iterator it = layoutModules_.begin();
1599 LayoutModuleList::const_iterator end = layoutModules_.end();
1600 for (; it != end; it++)
1603 layoutModules_.push_back(modName);
1608 Font const BufferParams::getFont() const
1610 FontInfo f = documentClass().defaultfont();
1611 if (fontsDefaultFamily == "rmdefault")
1612 f.setFamily(ROMAN_FAMILY);
1613 else if (fontsDefaultFamily == "sfdefault")
1614 f.setFamily(SANS_FAMILY);
1615 else if (fontsDefaultFamily == "ttdefault")
1616 f.setFamily(TYPEWRITER_FAMILY);
1617 return Font(f, language);
1621 void BufferParams::readPreamble(Lexer & lex)
1623 if (lex.getString() != "\\begin_preamble")
1624 lyxerr << "Error (BufferParams::readPreamble):"
1625 "consistency check failed." << endl;
1627 preamble = lex.getLongString("\\end_preamble");
1631 void BufferParams::readLocalLayout(Lexer & lex)
1633 if (lex.getString() != "\\begin_local_layout")
1634 lyxerr << "Error (BufferParams::readLocalLayout):"
1635 "consistency check failed." << endl;
1637 local_layout = lex.getLongString("\\end_local_layout");
1641 void BufferParams::readLanguage(Lexer & lex)
1643 if (!lex.next()) return;
1645 string const tmptok = lex.getString();
1647 // check if tmptok is part of tex_babel in tex-defs.h
1648 language = languages.getLanguage(tmptok);
1650 // Language tmptok was not found
1651 language = default_language;
1652 lyxerr << "Warning: Setting language `"
1653 << tmptok << "' to `" << language->lang()
1659 void BufferParams::readGraphicsDriver(Lexer & lex)
1664 string const tmptok = lex.getString();
1665 // check if tmptok is part of tex_graphics in tex_defs.h
1668 string const test = tex_graphics[n++];
1670 if (test == tmptok) {
1671 graphicsDriver = tmptok;
1676 "Warning: graphics driver `$$Token' not recognized!\n"
1677 " Setting graphics driver to `default'.\n");
1678 graphicsDriver = "default";
1685 void BufferParams::readBullets(Lexer & lex)
1690 int const index = lex.getInteger();
1692 int temp_int = lex.getInteger();
1693 user_defined_bullet(index).setFont(temp_int);
1694 temp_bullet(index).setFont(temp_int);
1696 user_defined_bullet(index).setCharacter(temp_int);
1697 temp_bullet(index).setCharacter(temp_int);
1699 user_defined_bullet(index).setSize(temp_int);
1700 temp_bullet(index).setSize(temp_int);
1704 void BufferParams::readBulletsLaTeX(Lexer & lex)
1706 // The bullet class should be able to read this.
1709 int const index = lex.getInteger();
1711 docstring const temp_str = lex.getDocString();
1713 user_defined_bullet(index).setText(temp_str);
1714 temp_bullet(index).setText(temp_str);
1718 void BufferParams::readModules(Lexer & lex)
1720 if (!lex.eatLine()) {
1721 lyxerr << "Error (BufferParams::readModules):"
1722 "Unexpected end of input." << endl;
1726 string mod = lex.getString();
1727 if (mod == "\\end_modules")
1729 addLayoutModule(mod);
1735 void BufferParams::readRemovedModules(Lexer & lex)
1737 if (!lex.eatLine()) {
1738 lyxerr << "Error (BufferParams::readRemovedModules):"
1739 "Unexpected end of input." << endl;
1743 string mod = lex.getString();
1744 if (mod == "\\end_removed_modules")
1746 removedModules_.push_back(mod);
1749 // now we want to remove any removed modules that were previously
1750 // added. normally, that will be because default modules were added in
1751 // setBaseClass(), which gets called when \textclass is read at the
1752 // start of the read.
1753 list<string>::const_iterator rit = removedModules_.begin();
1754 list<string>::const_iterator const ren = removedModules_.end();
1755 for (; rit != ren; rit++) {
1756 LayoutModuleList::iterator const mit = layoutModules_.begin();
1757 LayoutModuleList::iterator const men = layoutModules_.end();
1758 LayoutModuleList::iterator found = find(mit, men, *rit);
1761 layoutModules_.erase(found);
1766 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1768 char real_papersize = papersize;
1769 if (real_papersize == PAPER_DEFAULT)
1770 real_papersize = lyxrc.default_papersize;
1772 switch (real_papersize) {
1774 // could be anything, so don't guess
1776 case PAPER_CUSTOM: {
1777 if (purpose == XDVI && !paperwidth.empty() &&
1778 !paperheight.empty()) {
1779 // heightxwidth<unit>
1780 string first = paperwidth;
1781 string second = paperheight;
1782 if (orientation == ORIENTATION_LANDSCAPE)
1785 return first.erase(first.length() - 2)
1797 // dvips and dvipdfm do not know this
1798 if (purpose == DVIPS || purpose == DVIPDFM)
1802 // dvipdfm does not know this
1803 if (purpose == DVIPDFM)
1807 // dvipdfm does not know this
1808 if (purpose == DVIPDFM)
1811 case PAPER_USEXECUTIVE:
1812 // dvipdfm does not know this
1813 if (purpose == DVIPDFM)
1818 case PAPER_USLETTER:
1820 if (purpose == XDVI)
1827 string const BufferParams::dvips_options() const
1832 && papersize == PAPER_CUSTOM
1833 && !lyxrc.print_paper_dimension_flag.empty()
1834 && !paperwidth.empty()
1835 && !paperheight.empty()) {
1836 // using a custom papersize
1837 result = lyxrc.print_paper_dimension_flag;
1838 result += ' ' + paperwidth;
1839 result += ',' + paperheight;
1841 string const paper_option = paperSizeName(DVIPS);
1842 if (!paper_option.empty() && (paper_option != "letter" ||
1843 orientation != ORIENTATION_LANDSCAPE)) {
1844 // dvips won't accept -t letter -t landscape.
1845 // In all other cases, include the paper size
1847 result = lyxrc.print_paper_flag;
1848 result += ' ' + paper_option;
1851 if (orientation == ORIENTATION_LANDSCAPE &&
1852 papersize != PAPER_CUSTOM)
1853 result += ' ' + lyxrc.print_landscape_flag;
1858 string BufferParams::babelCall(string const & lang_opts) const
1860 string lang_pack = lyxrc.language_package;
1861 if (lang_pack != "\\usepackage{babel}")
1863 // suppress the babel call when there is no babel language defined
1864 // for the document language in the lib/languages file and if no
1865 // other languages are used (lang_opts is then empty)
1866 if (lang_opts.empty())
1868 // If Vietnamese is used, babel must directly be loaded with the
1869 // language options, see
1870 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1871 size_t viet = lang_opts.find("vietnam");
1872 // viet = string::npos when not found
1873 // the same is for all other languages that are not directly supported by
1874 // babel, but where LaTeX-packages add babel support.
1875 // this is currently the case for Latvian, Lithuanian, and Mongolian
1876 size_t latvian = lang_opts.find("latvian");
1877 size_t lithu = lang_opts.find("lithuanian");
1878 size_t mongo = lang_opts.find("mongolian");
1879 // If Japanese is used, babel must directly be loaded with the
1880 // language options, see
1881 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1882 size_t japan = lang_opts.find("japanese");
1883 if (!lyxrc.language_global_options || viet != string::npos
1884 || japan != string::npos || latvian != string::npos
1885 || lithu != string::npos || mongo != string::npos)
1886 return "\\usepackage[" + lang_opts + "]{babel}";
1891 docstring BufferParams::getGraphicsDriver(string const & package) const
1895 if (package == "geometry") {
1896 if (graphicsDriver == "dvips"
1897 || graphicsDriver == "dvipdfm"
1898 || graphicsDriver == "pdftex"
1899 || graphicsDriver == "vtex")
1900 result = from_ascii(graphicsDriver);
1901 else if (graphicsDriver == "dvipdfmx")
1902 result = from_ascii("dvipdfm");
1909 void BufferParams::writeEncodingPreamble(odocstream & os,
1910 LaTeXFeatures & features, TexRow & texrow) const
1914 if (inputenc == "auto") {
1915 string const doc_encoding =
1916 language->encoding()->latexName();
1917 Encoding::Package const package =
1918 language->encoding()->package();
1920 // Create a list with all the input encodings used
1922 set<string> encodings =
1923 features.getEncodingSet(doc_encoding);
1925 // If the "japanese" package (i.e. pLaTeX) is used,
1926 // inputenc must be omitted.
1927 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1928 if (package == Encoding::japanese)
1929 features.require("japanese");
1931 if ((!encodings.empty() || package == Encoding::inputenc)
1932 && !features.isRequired("japanese")) {
1933 os << "\\usepackage[";
1934 set<string>::const_iterator it = encodings.begin();
1935 set<string>::const_iterator const end = encodings.end();
1937 os << from_ascii(*it);
1940 for (; it != end; ++it)
1941 os << ',' << from_ascii(*it);
1942 if (package == Encoding::inputenc) {
1943 if (!encodings.empty())
1945 os << from_ascii(doc_encoding);
1947 os << "]{inputenc}\n";
1950 if (package == Encoding::CJK || features.mustProvide("CJK")) {
1951 if (language->encoding()->name() == "utf8-cjk"
1952 && LaTeXFeatures::isAvailable("CJKutf8"))
1953 os << "\\usepackage{CJKutf8}\n";
1955 os << "\\usepackage{CJK}\n";
1958 } else if (inputenc != "default") {
1959 switch (encoding().package()) {
1960 case Encoding::none:
1961 case Encoding::japanese:
1963 case Encoding::inputenc:
1964 // do not load inputenc if japanese is used
1965 if (features.isRequired("japanese"))
1967 os << "\\usepackage[" << from_ascii(inputenc)
1972 if (encoding().name() == "utf8-cjk"
1973 && LaTeXFeatures::isAvailable("CJKutf8"))
1974 os << "\\usepackage{CJKutf8}\n";
1976 os << "\\usepackage{CJK}\n";
1982 // The encoding "armscii8" (for Armenian) is only available when
1983 // the package "armtex" is loaded.
1984 if (language->encoding()->latexName() == "armscii8"
1985 || inputenc == "armscii8") {
1986 os << "\\usepackage{armtex}\n";
1992 string const BufferParams::parseFontName(string const & name) const
1994 string mangled = name;
1995 size_t const idx = mangled.find('[');
1996 if (idx == string::npos || idx == 0)
1999 return mangled.substr(0, idx - 1);
2003 string const BufferParams::loadFonts(string const & rm,
2004 string const & sf, string const & tt,
2005 bool const & sc, bool const & osf,
2006 int const & sfscale, int const & ttscale,
2007 bool const & xetex) const
2009 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2010 several packages have been replaced by others, that might not
2011 be installed on every system. We have to take care for that
2012 (see psnfss.pdf). We try to support all psnfss fonts as well
2013 as the fonts that have become de facto standard in the LaTeX
2014 world (e.g. Latin Modern). We do not support obsolete fonts
2015 (like PSLatex). In general, it should be possible to mix any
2016 rm font with any sf or tt font, respectively. (JSpitzm)
2018 -- separate math fonts.
2021 if (rm == "default" && sf == "default" && tt == "default")
2028 if (rm != "default")
2029 os << "\\setmainfont[Mapping=tex-text]{"
2030 << parseFontName(rm) << "}\n";
2031 if (sf != "default") {
2032 string const sans = parseFontName(sf);
2034 os << "\\setsansfont[Scale="
2035 << float(sfscale) / 100
2036 << ",Mapping=tex-text]{"
2039 os << "\\setsansfont[Mapping=tex-text]{"
2042 if (tt != "default") {
2043 string const mono = parseFontName(tt);
2045 os << "\\setmonofont[Scale="
2046 << float(sfscale) / 100
2050 os << "\\setmonofont[Mapping=tex-text]{"
2054 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2059 // Computer Modern (must be explicitely selectable -- there might be classes
2060 // that define a different default font!
2062 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2063 // osf for Computer Modern needs eco.sty
2065 os << "\\usepackage{eco}\n";
2067 // Latin Modern Roman
2068 else if (rm == "lmodern")
2069 os << "\\usepackage{lmodern}\n";
2071 else if (rm == "ae") {
2072 // not needed when using OT1 font encoding.
2073 if (lyxrc.fontenc != "default")
2074 os << "\\usepackage{ae,aecompl}\n";
2077 else if (rm == "times") {
2078 // try to load the best available package
2079 if (LaTeXFeatures::isAvailable("mathptmx"))
2080 os << "\\usepackage{mathptmx}\n";
2081 else if (LaTeXFeatures::isAvailable("mathptm"))
2082 os << "\\usepackage{mathptm}\n";
2084 os << "\\usepackage{times}\n";
2087 else if (rm == "palatino") {
2088 // try to load the best available package
2089 if (LaTeXFeatures::isAvailable("mathpazo")) {
2090 os << "\\usepackage";
2096 // "osf" includes "sc"!
2100 os << "{mathpazo}\n";
2102 else if (LaTeXFeatures::isAvailable("mathpple"))
2103 os << "\\usepackage{mathpple}\n";
2105 os << "\\usepackage{palatino}\n";
2108 else if (rm == "utopia") {
2109 // fourier supersedes utopia.sty, but does
2110 // not work with OT1 encoding.
2111 if (LaTeXFeatures::isAvailable("fourier")
2112 && lyxrc.fontenc != "default") {
2113 os << "\\usepackage";
2124 os << "{fourier}\n";
2127 os << "\\usepackage{utopia}\n";
2129 // Bera (complete fontset)
2130 else if (rm == "bera" && sf == "default" && tt == "default")
2131 os << "\\usepackage{bera}\n";
2133 else if (rm != "default")
2134 os << "\\usepackage" << "{" << rm << "}\n";
2137 // Helvetica, Bera Sans
2138 if (sf == "helvet" || sf == "berasans") {
2140 os << "\\usepackage[scaled=" << float(sfscale) / 100
2141 << "]{" << sf << "}\n";
2143 os << "\\usepackage{" << sf << "}\n";
2146 else if (sf == "avant")
2147 os << "\\usepackage{" << sf << "}\n";
2148 // Computer Modern, Latin Modern, CM Bright
2149 else if (sf != "default")
2150 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2152 // monospaced/typewriter
2153 // Courier, LuxiMono
2154 if (tt == "luximono" || tt == "beramono") {
2156 os << "\\usepackage[scaled=" << float(ttscale) / 100
2157 << "]{" << tt << "}\n";
2159 os << "\\usepackage{" << tt << "}\n";
2162 else if (tt == "courier" )
2163 os << "\\usepackage{" << tt << "}\n";
2164 // Computer Modern, Latin Modern, CM Bright
2165 else if (tt != "default")
2166 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2172 Encoding const & BufferParams::encoding() const
2175 return *(encodings.fromLaTeXName("utf8-plain"));
2176 if (inputenc == "auto" || inputenc == "default")
2177 return *language->encoding();
2178 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2181 LYXERR0("Unknown inputenc value `" << inputenc
2182 << "'. Using `auto' instead.");
2183 return *language->encoding();
2187 CiteEngine BufferParams::citeEngine() const
2189 // FIXME the class should provide the numerical/
2190 // authoryear choice
2191 if (documentClass().provides("natbib")
2192 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2193 return ENGINE_NATBIB_AUTHORYEAR;
2194 return cite_engine_;
2198 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2200 cite_engine_ = cite_engine;