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"
27 #include "Converter.h"
30 #include "IndicesList.h"
32 #include "LaTeXFeatures.h"
33 #include "ModuleList.h"
37 #include "OutputParams.h"
41 #include "PDFOptions.h"
43 #include "frontends/alert.h"
45 #include "insets/InsetListingsParams.h"
47 #include "support/convert.h"
48 #include "support/debug.h"
49 #include "support/docstream.h"
50 #include "support/FileName.h"
51 #include "support/filetools.h"
52 #include "support/gettext.h"
53 #include "support/Messages.h"
54 #include "support/Translator.h"
55 #include "support/lstrings.h"
61 using namespace lyx::support;
64 static char const * const string_paragraph_separation[] = {
69 static char const * const string_quotes_language[] = {
70 "english", "swedish", "german", "polish", "french", "danish", ""
74 static char const * const string_papersize[] = {
75 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
76 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
77 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
78 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
79 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
84 static char const * const string_orientation[] = {
85 "portrait", "landscape", ""
89 static char const * const string_footnotekinds[] = {
90 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
94 static char const * const tex_graphics[] = {
95 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
96 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
97 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
98 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
109 // Paragraph separation
110 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
113 ParSepTranslator const init_parseptranslator()
115 ParSepTranslator translator
116 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
117 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
122 ParSepTranslator const & parseptranslator()
124 static ParSepTranslator translator = init_parseptranslator();
130 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
133 QuotesLangTranslator const init_quoteslangtranslator()
135 QuotesLangTranslator translator
136 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
137 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
138 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
139 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
140 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
141 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
146 QuotesLangTranslator const & quoteslangtranslator()
148 static QuotesLangTranslator translator = init_quoteslangtranslator();
154 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
157 static PaperSizeTranslator initPaperSizeTranslator()
159 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
160 translator.addPair(string_papersize[1], PAPER_CUSTOM);
161 translator.addPair(string_papersize[2], PAPER_USLETTER);
162 translator.addPair(string_papersize[3], PAPER_USLEGAL);
163 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
164 translator.addPair(string_papersize[5], PAPER_A0);
165 translator.addPair(string_papersize[6], PAPER_A1);
166 translator.addPair(string_papersize[7], PAPER_A2);
167 translator.addPair(string_papersize[8], PAPER_A3);
168 translator.addPair(string_papersize[9], PAPER_A4);
169 translator.addPair(string_papersize[10], PAPER_A5);
170 translator.addPair(string_papersize[11], PAPER_A6);
171 translator.addPair(string_papersize[12], PAPER_B0);
172 translator.addPair(string_papersize[13], PAPER_B1);
173 translator.addPair(string_papersize[14], PAPER_B2);
174 translator.addPair(string_papersize[15], PAPER_B3);
175 translator.addPair(string_papersize[16], PAPER_B4);
176 translator.addPair(string_papersize[17], PAPER_B5);
177 translator.addPair(string_papersize[18], PAPER_B6);
178 translator.addPair(string_papersize[19], PAPER_C0);
179 translator.addPair(string_papersize[20], PAPER_C1);
180 translator.addPair(string_papersize[21], PAPER_C2);
181 translator.addPair(string_papersize[22], PAPER_C3);
182 translator.addPair(string_papersize[23], PAPER_C4);
183 translator.addPair(string_papersize[24], PAPER_C5);
184 translator.addPair(string_papersize[25], PAPER_C6);
185 translator.addPair(string_papersize[26], PAPER_JISB0);
186 translator.addPair(string_papersize[27], PAPER_JISB1);
187 translator.addPair(string_papersize[28], PAPER_JISB2);
188 translator.addPair(string_papersize[29], PAPER_JISB3);
189 translator.addPair(string_papersize[30], PAPER_JISB4);
190 translator.addPair(string_papersize[31], PAPER_JISB5);
191 translator.addPair(string_papersize[32], PAPER_JISB6);
196 PaperSizeTranslator const & papersizetranslator()
198 static PaperSizeTranslator translator = initPaperSizeTranslator();
204 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
207 PaperOrientationTranslator const init_paperorientationtranslator()
209 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
210 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
215 PaperOrientationTranslator const & paperorientationtranslator()
217 static PaperOrientationTranslator translator = init_paperorientationtranslator();
223 typedef Translator<int, PageSides> SidesTranslator;
226 SidesTranslator const init_sidestranslator()
228 SidesTranslator translator(1, OneSide);
229 translator.addPair(2, TwoSides);
234 SidesTranslator const & sidestranslator()
236 static SidesTranslator translator = init_sidestranslator();
242 typedef Translator<int, BufferParams::Package> PackageTranslator;
245 PackageTranslator const init_packagetranslator()
247 PackageTranslator translator(0, BufferParams::package_off);
248 translator.addPair(1, BufferParams::package_auto);
249 translator.addPair(2, BufferParams::package_on);
254 PackageTranslator const & packagetranslator()
256 static PackageTranslator translator = init_packagetranslator();
262 typedef Translator<string, CiteEngine> CiteEngineTranslator;
265 CiteEngineTranslator const init_citeenginetranslator()
267 CiteEngineTranslator translator("basic", ENGINE_BASIC);
268 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
269 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
270 translator.addPair("jurabib", ENGINE_JURABIB);
275 CiteEngineTranslator const & citeenginetranslator()
277 static CiteEngineTranslator translator = init_citeenginetranslator();
283 typedef Translator<string, Spacing::Space> SpaceTranslator;
286 SpaceTranslator const init_spacetranslator()
288 SpaceTranslator translator("default", Spacing::Default);
289 translator.addPair("single", Spacing::Single);
290 translator.addPair("onehalf", Spacing::Onehalf);
291 translator.addPair("double", Spacing::Double);
292 translator.addPair("other", Spacing::Other);
297 SpaceTranslator const & spacetranslator()
299 static SpaceTranslator translator = init_spacetranslator();
306 class BufferParams::Impl
311 AuthorList authorlist;
312 BranchList branchlist;
313 Bullet temp_bullets[4];
314 Bullet user_defined_bullets[4];
315 IndicesList indiceslist;
317 /** This is the amount of space used for paragraph_separation "skip",
318 * and for detached paragraphs in "indented" documents.
322 PDFOptions pdfoptions;
323 LayoutFileIndex baseClass_;
327 BufferParams::Impl::Impl()
328 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
330 // set initial author
332 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
337 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
341 return new BufferParams::Impl(*ptr);
345 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
351 BufferParams::BufferParams()
354 setBaseClass(defaultBaseclass());
356 paragraph_separation = ParagraphIndentSeparation;
357 quotes_language = InsetQuotes::EnglishQuotes;
358 fontsize = "default";
361 papersize = PAPER_DEFAULT;
362 orientation = ORIENTATION_PORTRAIT;
363 use_geometry = false;
364 cite_engine_ = ENGINE_BASIC;
365 biblio_style = "plain";
366 use_bibtopic = false;
368 trackChanges = false;
369 outputChanges = false;
370 use_default_options = true;
371 maintain_unincluded_children = false;
374 language = default_language;
376 fonts_roman = "default";
377 fonts_sans = "default";
378 fonts_typewriter = "default";
379 fonts_default_family = "default";
380 useNonTeXFonts = false;
381 fonts_expert_sc = false;
382 fonts_old_figures = false;
383 fonts_sans_scale = 100;
384 fonts_typewriter_scale = 100;
386 lang_package = "default";
387 graphics_driver = "default";
388 default_output_format = "default";
389 bibtex_command = "default";
390 index_command = "default";
393 listings_params = string();
394 pagestyle = "default";
395 suppress_date = false;
396 justification = true;
397 // no color is the default (white)
398 backgroundcolor = lyx::rgbFromHexName("#ffffff");
399 isbackgroundcolor = false;
400 // no color is the default (black)
401 fontcolor = lyx::rgbFromHexName("#000000");
403 // light gray is the default font color for greyed-out notes
404 notefontcolor = lyx::rgbFromHexName("#cccccc");
405 boxbgcolor = lyx::rgbFromHexName("#ff0000");
406 compressed = lyxrc.save_compressed;
407 for (int iter = 0; iter < 4; ++iter) {
408 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
409 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
412 indiceslist().addDefault(B_("Index"));
413 html_be_strict = false;
414 html_math_output = MathML;
415 html_math_img_scale = 1.0;
416 html_css_as_file = false;
423 docstring BufferParams::B_(string const & l10n) const
425 LASSERT(language, /**/);
426 return getMessages(language->code()).get(l10n);
430 BufferParams::Package BufferParams::use_package(std::string const & p) const
432 PackageMap::const_iterator it = use_packages.find(p);
433 if (it == use_packages.end())
439 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
445 vector<string> const & BufferParams::auto_packages()
447 static vector<string> packages;
448 if (packages.empty()) {
449 // adding a package here implies a file format change!
450 packages.push_back("amsmath");
451 packages.push_back("esint");
452 packages.push_back("mathdots");
453 packages.push_back("mathtools");
454 packages.push_back("mhchem");
455 packages.push_back("undertilde");
461 AuthorList & BufferParams::authors()
463 return pimpl_->authorlist;
467 AuthorList const & BufferParams::authors() const
469 return pimpl_->authorlist;
473 BranchList & BufferParams::branchlist()
475 return pimpl_->branchlist;
479 BranchList const & BufferParams::branchlist() const
481 return pimpl_->branchlist;
485 IndicesList & BufferParams::indiceslist()
487 return pimpl_->indiceslist;
491 IndicesList const & BufferParams::indiceslist() const
493 return pimpl_->indiceslist;
497 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
499 LASSERT(index < 4, /**/);
500 return pimpl_->temp_bullets[index];
504 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
506 LASSERT(index < 4, /**/);
507 return pimpl_->temp_bullets[index];
511 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
513 LASSERT(index < 4, /**/);
514 return pimpl_->user_defined_bullets[index];
518 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
520 LASSERT(index < 4, /**/);
521 return pimpl_->user_defined_bullets[index];
525 Spacing & BufferParams::spacing()
527 return pimpl_->spacing;
531 Spacing const & BufferParams::spacing() const
533 return pimpl_->spacing;
537 PDFOptions & BufferParams::pdfoptions()
539 return pimpl_->pdfoptions;
543 PDFOptions const & BufferParams::pdfoptions() const
545 return pimpl_->pdfoptions;
549 HSpace const & BufferParams::getIndentation() const
551 return pimpl_->indentation;
555 void BufferParams::setIndentation(HSpace const & indent)
557 pimpl_->indentation = indent;
561 VSpace const & BufferParams::getDefSkip() const
563 return pimpl_->defskip;
567 void BufferParams::setDefSkip(VSpace const & vs)
569 // DEFSKIP will cause an infinite loop
570 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
571 pimpl_->defskip = vs;
575 string BufferParams::readToken(Lexer & lex, string const & token,
576 FileName const & filepath)
578 if (token == "\\textclass") {
580 string const classname = lex.getString();
581 // if there exists a local layout file, ignore the system one
582 // NOTE: in this case, the textclass (.cls file) is assumed to
585 LayoutFileList & bcl = LayoutFileList::get();
586 if (tcp.empty() && !filepath.empty())
587 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
591 setBaseClass(classname);
592 // We assume that a tex class exists for local or unknown
593 // layouts so this warning, will only be given for system layouts.
594 if (!baseClass()->isTeXClassAvailable()) {
595 docstring const desc =
596 translateIfPossible(from_utf8(baseClass()->description()));
597 docstring const prereqs =
598 from_utf8(baseClass()->prerequisites());
599 docstring const msg =
600 bformat(_("The selected document class\n"
602 "requires external files that are not available.\n"
603 "The document class can still be used, but the\n"
604 "document cannot be compiled until the following\n"
605 "prerequisites are installed:\n"
607 "See section 3.1.2.2 (Class Availability) of the\n"
608 "User's Guide for more information."), desc, prereqs);
609 frontend::Alert::warning(_("Document class not available"),
612 } else if (token == "\\begin_preamble") {
614 } else if (token == "\\begin_local_layout") {
615 readLocalLayout(lex);
616 } else if (token == "\\begin_modules") {
618 } else if (token == "\\begin_removed_modules") {
619 readRemovedModules(lex);
620 } else if (token == "\\begin_includeonly") {
621 readIncludeonly(lex);
622 } else if (token == "\\maintain_unincluded_children") {
623 lex >> maintain_unincluded_children;
624 } else if (token == "\\options") {
626 options = lex.getString();
627 } else if (token == "\\use_default_options") {
628 lex >> use_default_options;
629 } else if (token == "\\master") {
631 master = lex.getString();
632 } else if (token == "\\suppress_date") {
633 lex >> suppress_date;
634 } else if (token == "\\justification") {
635 lex >> justification;
636 } else if (token == "\\language") {
638 } else if (token == "\\language_package") {
640 lang_package = lex.getString();
641 } else if (token == "\\inputencoding") {
643 } else if (token == "\\graphics") {
644 readGraphicsDriver(lex);
645 } else if (token == "\\default_output_format") {
646 lex >> default_output_format;
647 } else if (token == "\\bibtex_command") {
649 bibtex_command = lex.getString();
650 } else if (token == "\\index_command") {
652 index_command = lex.getString();
653 } else if (token == "\\fontencoding") {
655 fontenc = lex.getString();
656 } else if (token == "\\font_roman") {
658 fonts_roman = lex.getString();
659 } else if (token == "\\font_sans") {
661 fonts_sans = lex.getString();
662 } else if (token == "\\font_typewriter") {
664 fonts_typewriter = lex.getString();
665 } else if (token == "\\font_default_family") {
666 lex >> fonts_default_family;
667 } else if (token == "\\use_non_tex_fonts") {
668 lex >> useNonTeXFonts;
669 } else if (token == "\\font_sc") {
670 lex >> fonts_expert_sc;
671 } else if (token == "\\font_osf") {
672 lex >> fonts_old_figures;
673 } else if (token == "\\font_sf_scale") {
674 lex >> fonts_sans_scale;
675 } else if (token == "\\font_tt_scale") {
676 lex >> fonts_typewriter_scale;
677 } else if (token == "\\font_cjk") {
679 } else if (token == "\\paragraph_separation") {
682 paragraph_separation = parseptranslator().find(parsep);
683 } else if (token == "\\paragraph_indentation") {
685 string indentation = lex.getString();
686 pimpl_->indentation = HSpace(indentation);
687 } else if (token == "\\defskip") {
689 string const defskip = lex.getString();
690 pimpl_->defskip = VSpace(defskip);
691 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
693 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
694 } else if (token == "\\quotes_language") {
697 quotes_language = quoteslangtranslator().find(quotes_lang);
698 } else if (token == "\\papersize") {
701 papersize = papersizetranslator().find(ppsize);
702 } else if (token == "\\use_geometry") {
704 } else if (token == "\\use_package") {
709 use_package(package, packagetranslator().find(use));
710 } else if (token == "\\cite_engine") {
713 cite_engine_ = citeenginetranslator().find(engine);
714 } else if (token == "\\biblio_style") {
716 biblio_style = lex.getString();
717 } else if (token == "\\use_bibtopic") {
719 } else if (token == "\\use_indices") {
721 } else if (token == "\\tracking_changes") {
723 } else if (token == "\\output_changes") {
724 lex >> outputChanges;
725 } else if (token == "\\branch") {
727 docstring branch = lex.getDocString();
728 branchlist().add(branch);
731 string const tok = lex.getString();
732 if (tok == "\\end_branch")
734 Branch * branch_ptr = branchlist().find(branch);
735 if (tok == "\\selected") {
738 branch_ptr->setSelected(lex.getInteger());
740 if (tok == "\\filename_suffix") {
743 branch_ptr->setFileNameSuffix(lex.getInteger());
745 if (tok == "\\color") {
747 string color = lex.getString();
749 branch_ptr->setColor(color);
750 // Update also the Color table:
752 color = lcolor.getX11Name(Color_background);
754 lcolor.setColor(to_utf8(branch), color);
757 } else if (token == "\\index") {
759 docstring index = lex.getDocString();
761 indiceslist().add(index);
764 string const tok = lex.getString();
765 if (tok == "\\end_index")
767 Index * index_ptr = indiceslist().find(index);
768 if (tok == "\\shortcut") {
770 shortcut = lex.getDocString();
772 index_ptr->setShortcut(shortcut);
774 if (tok == "\\color") {
776 string color = lex.getString();
778 index_ptr->setColor(color);
779 // Update also the Color table:
781 color = lcolor.getX11Name(Color_background);
783 if (!shortcut.empty())
784 lcolor.setColor(to_utf8(shortcut), color);
787 } else if (token == "\\author") {
789 istringstream ss(lex.getString());
792 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
793 } else if (token == "\\paperorientation") {
796 orientation = paperorientationtranslator().find(orient);
797 } else if (token == "\\backgroundcolor") {
799 backgroundcolor = lyx::rgbFromHexName(lex.getString());
800 isbackgroundcolor = true;
801 } else if (token == "\\fontcolor") {
803 fontcolor = lyx::rgbFromHexName(lex.getString());
805 } else if (token == "\\notefontcolor") {
807 string color = lex.getString();
808 notefontcolor = lyx::rgbFromHexName(color);
809 } else if (token == "\\boxbgcolor") {
811 string color = lex.getString();
812 boxbgcolor = lyx::rgbFromHexName(color);
813 } else if (token == "\\paperwidth") {
815 } else if (token == "\\paperheight") {
817 } else if (token == "\\leftmargin") {
819 } else if (token == "\\topmargin") {
821 } else if (token == "\\rightmargin") {
823 } else if (token == "\\bottommargin") {
825 } else if (token == "\\headheight") {
827 } else if (token == "\\headsep") {
829 } else if (token == "\\footskip") {
831 } else if (token == "\\columnsep") {
833 } else if (token == "\\paperfontsize") {
835 } else if (token == "\\papercolumns") {
837 } else if (token == "\\listings_params") {
840 listings_params = InsetListingsParams(par).params();
841 } else if (token == "\\papersides") {
844 sides = sidestranslator().find(psides);
845 } else if (token == "\\paperpagestyle") {
847 } else if (token == "\\bullet") {
849 } else if (token == "\\bulletLaTeX") {
850 readBulletsLaTeX(lex);
851 } else if (token == "\\secnumdepth") {
853 } else if (token == "\\tocdepth") {
855 } else if (token == "\\spacing") {
859 if (nspacing == "other") {
862 spacing().set(spacetranslator().find(nspacing), tmp_val);
863 } else if (token == "\\float_placement") {
864 lex >> float_placement;
866 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
867 string toktmp = pdfoptions().readToken(lex, token);
868 if (!toktmp.empty()) {
869 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
873 } else if (token == "\\html_math_output") {
876 html_math_output = static_cast<MathOutput>(temp);
877 } else if (token == "\\html_be_strict") {
878 lex >> html_be_strict;
879 } else if (token == "\\html_css_as_file") {
880 lex >> html_css_as_file;
881 } else if (token == "\\html_math_img_scale") {
882 lex >> html_math_img_scale;
883 } else if (token == "\\html_latex_start") {
885 html_latex_start = lex.getString();
886 } else if (token == "\\html_latex_end") {
888 html_latex_end = lex.getString();
889 } else if (token == "\\output_sync") {
891 } else if (token == "\\output_sync_macro") {
892 lex >> output_sync_macro;
893 } else if (token == "\\use_refstyle") {
896 lyxerr << "BufferParams::readToken(): Unknown token: " <<
905 void BufferParams::writeFile(ostream & os) const
907 // The top of the file is written by the buffer.
908 // Prints out the buffer info into the .lyx file given by file
911 os << "\\textclass " << baseClass()->name() << '\n';
914 if (!preamble.empty()) {
915 // remove '\n' from the end of preamble
916 string const tmppreamble = rtrim(preamble, "\n");
917 os << "\\begin_preamble\n"
919 << "\n\\end_preamble\n";
923 if (!options.empty()) {
924 os << "\\options " << options << '\n';
927 // use the class options defined in the layout?
928 os << "\\use_default_options "
929 << convert<string>(use_default_options) << "\n";
931 // the master document
932 if (!master.empty()) {
933 os << "\\master " << master << '\n';
937 if (!removed_modules_.empty()) {
938 os << "\\begin_removed_modules" << '\n';
939 list<string>::const_iterator it = removed_modules_.begin();
940 list<string>::const_iterator en = removed_modules_.end();
941 for (; it != en; it++)
943 os << "\\end_removed_modules" << '\n';
947 if (!layout_modules_.empty()) {
948 os << "\\begin_modules" << '\n';
949 LayoutModuleList::const_iterator it = layout_modules_.begin();
950 LayoutModuleList::const_iterator en = layout_modules_.end();
951 for (; it != en; it++)
953 os << "\\end_modules" << '\n';
957 if (!included_children_.empty()) {
958 os << "\\begin_includeonly" << '\n';
959 list<string>::const_iterator it = included_children_.begin();
960 list<string>::const_iterator en = included_children_.end();
961 for (; it != en; it++)
963 os << "\\end_includeonly" << '\n';
965 os << "\\maintain_unincluded_children "
966 << convert<string>(maintain_unincluded_children) << '\n';
968 // local layout information
969 if (!local_layout.empty()) {
970 // remove '\n' from the end
971 string const tmplocal = rtrim(local_layout, "\n");
972 os << "\\begin_local_layout\n"
974 << "\n\\end_local_layout\n";
977 // then the text parameters
978 if (language != ignore_language)
979 os << "\\language " << language->lang() << '\n';
980 os << "\\language_package " << lang_package
981 << "\n\\inputencoding " << inputenc
982 << "\n\\fontencoding " << fontenc
983 << "\n\\font_roman " << fonts_roman
984 << "\n\\font_sans " << fonts_sans
985 << "\n\\font_typewriter " << fonts_typewriter
986 << "\n\\font_default_family " << fonts_default_family
987 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
988 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
989 << "\n\\font_osf " << convert<string>(fonts_old_figures)
990 << "\n\\font_sf_scale " << fonts_sans_scale
991 << "\n\\font_tt_scale " << fonts_typewriter_scale
993 if (!fonts_cjk.empty()) {
994 os << "\\font_cjk " << fonts_cjk << '\n';
996 os << "\n\\graphics " << graphics_driver << '\n';
997 os << "\\default_output_format " << default_output_format << '\n';
998 os << "\\output_sync " << output_sync << '\n';
999 if (!output_sync_macro.empty())
1000 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1001 os << "\\bibtex_command " << bibtex_command << '\n';
1002 os << "\\index_command " << index_command << '\n';
1004 if (!float_placement.empty()) {
1005 os << "\\float_placement " << float_placement << '\n';
1007 os << "\\paperfontsize " << fontsize << '\n';
1009 spacing().writeFile(os);
1010 pdfoptions().writeFile(os);
1012 os << "\\papersize " << string_papersize[papersize]
1013 << "\n\\use_geometry " << convert<string>(use_geometry);
1014 vector<string> const & packages = auto_packages();
1015 for (size_t i = 0; i < packages.size(); ++i)
1016 os << "\n\\use_package " << packages[i] << ' '
1017 << use_package(packages[i]);
1018 os << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
1019 << "\n\\biblio_style " << biblio_style
1020 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1021 << "\n\\use_indices " << convert<string>(use_indices)
1022 << "\n\\paperorientation " << string_orientation[orientation]
1023 << "\n\\suppress_date " << convert<string>(suppress_date)
1024 << "\n\\justification " << convert<string>(justification)
1025 << "\n\\use_refstyle " << use_refstyle
1027 if (isbackgroundcolor == true)
1028 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1029 if (isfontcolor == true)
1030 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1031 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1032 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1033 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1034 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1036 BranchList::const_iterator it = branchlist().begin();
1037 BranchList::const_iterator end = branchlist().end();
1038 for (; it != end; ++it) {
1039 os << "\\branch " << to_utf8(it->branch())
1040 << "\n\\selected " << it->isSelected()
1041 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1042 << "\n\\color " << lyx::X11hexname(it->color())
1047 IndicesList::const_iterator iit = indiceslist().begin();
1048 IndicesList::const_iterator iend = indiceslist().end();
1049 for (; iit != iend; ++iit) {
1050 os << "\\index " << to_utf8(iit->index())
1051 << "\n\\shortcut " << to_utf8(iit->shortcut())
1052 << "\n\\color " << lyx::X11hexname(iit->color())
1057 if (!paperwidth.empty())
1058 os << "\\paperwidth "
1059 << VSpace(paperwidth).asLyXCommand() << '\n';
1060 if (!paperheight.empty())
1061 os << "\\paperheight "
1062 << VSpace(paperheight).asLyXCommand() << '\n';
1063 if (!leftmargin.empty())
1064 os << "\\leftmargin "
1065 << VSpace(leftmargin).asLyXCommand() << '\n';
1066 if (!topmargin.empty())
1067 os << "\\topmargin "
1068 << VSpace(topmargin).asLyXCommand() << '\n';
1069 if (!rightmargin.empty())
1070 os << "\\rightmargin "
1071 << VSpace(rightmargin).asLyXCommand() << '\n';
1072 if (!bottommargin.empty())
1073 os << "\\bottommargin "
1074 << VSpace(bottommargin).asLyXCommand() << '\n';
1075 if (!headheight.empty())
1076 os << "\\headheight "
1077 << VSpace(headheight).asLyXCommand() << '\n';
1078 if (!headsep.empty())
1080 << VSpace(headsep).asLyXCommand() << '\n';
1081 if (!footskip.empty())
1083 << VSpace(footskip).asLyXCommand() << '\n';
1084 if (!columnsep.empty())
1085 os << "\\columnsep "
1086 << VSpace(columnsep).asLyXCommand() << '\n';
1087 os << "\\secnumdepth " << secnumdepth
1088 << "\n\\tocdepth " << tocdepth
1089 << "\n\\paragraph_separation "
1090 << string_paragraph_separation[paragraph_separation];
1091 if (!paragraph_separation)
1092 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1094 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1095 os << "\n\\quotes_language "
1096 << string_quotes_language[quotes_language]
1097 << "\n\\papercolumns " << columns
1098 << "\n\\papersides " << sides
1099 << "\n\\paperpagestyle " << pagestyle << '\n';
1100 if (!listings_params.empty())
1101 os << "\\listings_params \"" <<
1102 InsetListingsParams(listings_params).encodedString() << "\"\n";
1103 for (int i = 0; i < 4; ++i) {
1104 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1105 if (user_defined_bullet(i).getFont() != -1) {
1106 os << "\\bullet " << i << " "
1107 << user_defined_bullet(i).getFont() << " "
1108 << user_defined_bullet(i).getCharacter() << " "
1109 << user_defined_bullet(i).getSize() << "\n";
1113 os << "\\bulletLaTeX " << i << " \""
1114 << lyx::to_ascii(user_defined_bullet(i).getText())
1120 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1121 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1122 << "\\html_math_output " << html_math_output << '\n'
1123 << "\\html_css_as_file " << html_css_as_file << '\n'
1124 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1126 if (html_math_img_scale != 1.0)
1127 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1128 if (!html_latex_start.empty())
1129 os << "\\html_latex_start " << html_latex_start << '\n';
1130 if (!html_latex_end.empty())
1131 os << "\\html_latex_end " << html_latex_end << '\n';
1133 os << pimpl_->authorlist;
1137 void BufferParams::validate(LaTeXFeatures & features) const
1139 features.require(documentClass().requires());
1141 if (outputChanges) {
1142 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1143 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1144 LaTeXFeatures::isAvailable("xcolor");
1146 switch (features.runparams().flavor) {
1147 case OutputParams::LATEX:
1148 case OutputParams::DVILUATEX:
1150 features.require("ct-dvipost");
1151 features.require("dvipost");
1152 } else if (xcolorulem) {
1153 features.require("ct-xcolor-ulem");
1154 features.require("ulem");
1155 features.require("xcolor");
1157 features.require("ct-none");
1160 case OutputParams::LUATEX:
1161 case OutputParams::PDFLATEX:
1162 case OutputParams::XETEX:
1164 features.require("ct-xcolor-ulem");
1165 features.require("ulem");
1166 features.require("xcolor");
1167 // improves color handling in PDF output
1168 features.require("pdfcolmk");
1170 features.require("ct-none");
1178 // Floats with 'Here definitely' as default setting.
1179 if (float_placement.find('H') != string::npos)
1180 features.require("float");
1182 for (PackageMap::const_iterator it = use_packages.begin();
1183 it != use_packages.end(); ++it) {
1184 if (it->first == "amsmath") {
1185 // AMS Style is at document level
1186 if (it->second == package_on ||
1187 documentClass().provides("amsmath"))
1188 features.require(it->first);
1189 } else if (it->second == package_on)
1190 features.require(it->first);
1193 // Document-level line spacing
1194 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1195 features.require("setspace");
1197 // the bullet shapes are buffer level not paragraph level
1198 // so they are tested here
1199 for (int i = 0; i < 4; ++i) {
1200 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1202 int const font = user_defined_bullet(i).getFont();
1204 int const c = user_defined_bullet(i).getCharacter();
1210 features.require("latexsym");
1212 } else if (font == 1) {
1213 features.require("amssymb");
1214 } else if (font >= 2 && font <= 5) {
1215 features.require("pifont");
1219 if (pdfoptions().use_hyperref) {
1220 features.require("hyperref");
1221 // due to interferences with babel and hyperref, the color package has to
1222 // be loaded after hyperref when hyperref is used with the colorlinks
1223 // option, see http://www.lyx.org/trac/ticket/5291
1224 if (pdfoptions().colorlinks)
1225 features.require("color");
1228 if (features.runparams().flavor == OutputParams::XETEX
1230 features.require("polyglossia");
1232 if (language->lang() == "vietnamese")
1233 features.require("vietnamese");
1234 else if (language->lang() == "japanese")
1235 features.require("japanese");
1239 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1240 FileName const & filepath) const
1242 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1243 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1244 // \RequirePackage to do so, rather than the normal \usepackage
1245 // Do not try to load any other package before the document class, unless you
1246 // have a thorough understanding of the LATEX internals and know exactly what you
1248 if (features.mustProvide("fix-cm"))
1249 os << "\\RequirePackage{fix-cm}\n";
1251 os << "\\documentclass";
1253 DocumentClass const & tclass = documentClass();
1255 ostringstream clsoptions; // the document class options.
1257 if (tokenPos(tclass.opt_fontsize(),
1258 '|', fontsize) >= 0) {
1259 // only write if existing in list (and not default)
1260 clsoptions << fontsize << "pt,";
1263 // all paper sizes except of A4, A5, B5 and the US sizes need the
1265 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1266 && papersize != PAPER_USLETTER
1267 && papersize != PAPER_USLEGAL
1268 && papersize != PAPER_USEXECUTIVE
1269 && papersize != PAPER_A4
1270 && papersize != PAPER_A5
1271 && papersize != PAPER_B5;
1273 if (!use_geometry) {
1274 switch (papersize) {
1276 clsoptions << "a4paper,";
1278 case PAPER_USLETTER:
1279 clsoptions << "letterpaper,";
1282 clsoptions << "a5paper,";
1285 clsoptions << "b5paper,";
1287 case PAPER_USEXECUTIVE:
1288 clsoptions << "executivepaper,";
1291 clsoptions << "legalpaper,";
1325 if (sides != tclass.sides()) {
1328 clsoptions << "oneside,";
1331 clsoptions << "twoside,";
1337 if (columns != tclass.columns()) {
1339 clsoptions << "twocolumn,";
1341 clsoptions << "onecolumn,";
1345 && orientation == ORIENTATION_LANDSCAPE)
1346 clsoptions << "landscape,";
1348 // language should be a parameter to \documentclass
1349 if (language->babel() == "hebrew"
1350 && default_language->babel() != "hebrew")
1351 // This seems necessary
1352 features.useLanguage(default_language);
1354 ostringstream language_options;
1355 bool const use_babel = features.useBabel() && !tclass.provides("babel");
1356 bool const use_polyglossia = features.usePolyglossia();
1357 bool const global = lyxrc.language_global_options;
1358 if (use_babel || (use_polyglossia && global)) {
1359 language_options << features.getLanguages();
1360 if (!language->babel().empty()) {
1361 if (!language_options.str().empty())
1362 language_options << ',';
1363 language_options << language->babel();
1365 if (global && !features.needBabelLangOptions())
1366 clsoptions << language_options.str() << ',';
1369 // the predefined options from the layout
1370 if (use_default_options && !tclass.options().empty())
1371 clsoptions << tclass.options() << ',';
1373 // the user-defined options
1374 if (!options.empty()) {
1375 clsoptions << options << ',';
1378 string strOptions(clsoptions.str());
1379 if (!strOptions.empty()) {
1380 strOptions = rtrim(strOptions, ",");
1382 os << '[' << from_utf8(strOptions) << ']';
1385 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1386 // end of \documentclass defs
1388 // if we use fontspec, we have to load the AMS packages here
1389 string const ams = features.loadAMSPackages();
1390 if (useNonTeXFonts && !ams.empty())
1391 os << from_ascii(ams);
1394 os << "\\usepackage{fontspec}\n";
1396 // font selection must be done before loading fontenc.sty
1397 string const fonts =
1398 loadFonts(fonts_roman, fonts_sans, fonts_typewriter,
1399 fonts_expert_sc, fonts_old_figures,
1400 fonts_sans_scale, fonts_typewriter_scale,
1401 useNonTeXFonts, features);
1403 os << from_utf8(fonts);
1405 if (fonts_default_family != "default")
1406 os << "\\renewcommand{\\familydefault}{\\"
1407 << from_ascii(fonts_default_family) << "}\n";
1409 // set font encoding
1410 // for arabic_arabi and farsi we also need to load the LAE and
1412 // XeTeX and LuaTeX (with OS fonts) work without fontenc
1413 if (font_encoding() != "default" && language->lang() != "japanese"
1414 && !useNonTeXFonts && !tclass.provides("fontenc")) {
1415 size_t fars = language_options.str().find("farsi");
1416 size_t arab = language_options.str().find("arabic");
1417 if (language->lang() == "arabic_arabi"
1418 || language->lang() == "farsi" || fars != string::npos
1419 || arab != string::npos) {
1420 os << "\\usepackage[" << from_ascii(font_encoding())
1421 << ",LFE,LAE]{fontenc}\n";
1423 os << "\\usepackage[" << from_ascii(font_encoding())
1428 // handle inputenc etc.
1429 writeEncodingPreamble(os, features);
1432 if (!features.runparams().includeall && !included_children_.empty()) {
1433 os << "\\includeonly{";
1434 list<string>::const_iterator it = included_children_.begin();
1435 list<string>::const_iterator en = included_children_.end();
1437 for (; it != en; ++it) {
1438 string incfile = *it;
1439 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1440 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1442 if (!features.runparams().nice)
1444 // \includeonly doesn't want an extension
1445 incfile = changeExtension(incfile, string());
1446 incfile = support::latex_path(incfile);
1447 if (!incfile.empty()) {
1450 os << from_utf8(incfile);
1457 if (!listings_params.empty() || features.isRequired("listings"))
1458 os << "\\usepackage{listings}\n";
1460 if (!listings_params.empty()) {
1462 // do not test validity because listings_params is
1463 // supposed to be valid
1465 InsetListingsParams(listings_params).separatedParams(true);
1466 // we can't support all packages, but we should load the color package
1467 if (par.find("\\color", 0) != string::npos)
1468 features.require("color");
1469 os << from_utf8(par)
1472 if (!tclass.provides("geometry")
1473 && (use_geometry || nonstandard_papersize)) {
1474 odocstringstream ods;
1475 if (!getGraphicsDriver("geometry").empty())
1476 ods << getGraphicsDriver("geometry");
1477 if (orientation == ORIENTATION_LANDSCAPE)
1478 ods << ",landscape";
1479 switch (papersize) {
1481 if (!paperwidth.empty())
1482 ods << ",paperwidth="
1483 << from_ascii(paperwidth);
1484 if (!paperheight.empty())
1485 ods << ",paperheight="
1486 << from_ascii(paperheight);
1488 case PAPER_USLETTER:
1489 ods << ",letterpaper";
1492 ods << ",legalpaper";
1494 case PAPER_USEXECUTIVE:
1495 ods << ",executivepaper";
1584 docstring const g_options = trim(ods.str(), ",");
1585 os << "\\usepackage";
1586 if (!g_options.empty())
1587 os << '[' << g_options << ']';
1588 os << "{geometry}\n";
1589 // output this only if use_geometry is true
1591 os << "\\geometry{verbose";
1592 if (!topmargin.empty())
1593 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1594 if (!bottommargin.empty())
1595 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1596 if (!leftmargin.empty())
1597 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1598 if (!rightmargin.empty())
1599 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1600 if (!headheight.empty())
1601 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1602 if (!headsep.empty())
1603 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1604 if (!footskip.empty())
1605 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1606 if (!columnsep.empty())
1607 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1610 } else if (orientation == ORIENTATION_LANDSCAPE
1611 || papersize != PAPER_DEFAULT) {
1612 features.require("papersize");
1615 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1616 if (pagestyle == "fancy")
1617 os << "\\usepackage{fancyhdr}\n";
1618 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1621 // only output when the background color is not default
1622 if (isbackgroundcolor == true) {
1623 // only require color here, the background color will be defined
1624 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1626 features.require("color");
1627 features.require("pagecolor");
1630 // only output when the font color is not default
1631 if (isfontcolor == true) {
1632 // only require color here, the font color will be defined
1633 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1635 features.require("color");
1636 features.require("fontcolor");
1639 // Only if class has a ToC hierarchy
1640 if (tclass.hasTocLevels()) {
1641 if (secnumdepth != tclass.secnumdepth()) {
1642 os << "\\setcounter{secnumdepth}{"
1646 if (tocdepth != tclass.tocdepth()) {
1647 os << "\\setcounter{tocdepth}{"
1653 if (paragraph_separation) {
1654 // when skip separation
1655 switch (getDefSkip().kind()) {
1656 case VSpace::SMALLSKIP:
1657 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1659 case VSpace::MEDSKIP:
1660 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1662 case VSpace::BIGSKIP:
1663 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1665 case VSpace::LENGTH:
1666 os << "\\setlength{\\parskip}{"
1667 << from_utf8(getDefSkip().length().asLatexString())
1670 default: // should never happen // Then delete it.
1671 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1674 os << "\\setlength{\\parindent}{0pt}\n";
1676 // when separation by indentation
1677 // only output something when a width is given
1678 if (getIndentation().asLyXCommand() != "default") {
1679 os << "\\setlength{\\parindent}{"
1680 << from_utf8(getIndentation().asLatexCommand())
1685 // Now insert the LyX specific LaTeX commands...
1686 docstring lyxpreamble;
1687 features.resolveAlternatives();
1690 if (!output_sync_macro.empty())
1691 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1692 else if (features.runparams().flavor == OutputParams::LATEX)
1693 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1694 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1695 lyxpreamble += "\\synctex=-1\n";
1698 // due to interferences with babel and hyperref, the color package has to
1699 // be loaded (when it is not already loaded) before babel when hyperref
1700 // is used with the colorlinks option, see
1701 // http://www.lyx.org/trac/ticket/5291
1702 // we decided therefore to load color always before babel, see
1703 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1704 lyxpreamble += from_ascii(features.getColorOptions());
1706 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1708 && (features.isRequired("jurabib")
1709 || features.isRequired("hyperref")
1710 || features.isRequired("vietnamese")
1711 || features.isRequired("japanese"))) {
1713 lyxpreamble += from_utf8(features.getBabelPresettings());
1714 lyxpreamble += from_utf8(babelCall(language_options.str(),
1715 features.needBabelLangOptions())) + '\n';
1716 lyxpreamble += from_utf8(features.getBabelPostsettings());
1719 // The optional packages;
1720 lyxpreamble += from_ascii(features.getPackages());
1722 // Additional Indices
1723 if (features.isRequired("splitidx")) {
1724 IndicesList::const_iterator iit = indiceslist().begin();
1725 IndicesList::const_iterator iend = indiceslist().end();
1726 for (; iit != iend; ++iit) {
1727 lyxpreamble += "\\newindex[";
1728 lyxpreamble += iit->index();
1729 lyxpreamble += "]{";
1730 lyxpreamble += iit->shortcut();
1731 lyxpreamble += "}\n";
1736 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1739 // * Hyperref manual: "Make sure it comes last of your loaded
1740 // packages, to give it a fighting chance of not being over-written,
1741 // since its job is to redefine many LaTeX commands."
1742 // * Email from Heiko Oberdiek: "It is usually better to load babel
1743 // before hyperref. Then hyperref has a chance to detect babel.
1744 // * Has to be loaded before the "LyX specific LaTeX commands" to
1745 // avoid errors with algorithm floats.
1746 // use hyperref explicitly if it is required
1747 if (features.isRequired("hyperref")) {
1748 // pass what we have to stream here, since we need
1749 // to access the stream itself in PDFOptions.
1752 OutputParams tmp_params = features.runparams();
1753 pdfoptions().writeLaTeX(tmp_params, os,
1754 documentClass().provides("hyperref"));
1755 // set back for the rest
1756 lyxpreamble.clear();
1757 // correctly break URLs with hyperref and dvi output
1758 if (features.runparams().flavor == OutputParams::LATEX
1759 && features.isAvailable("breakurl"))
1760 lyxpreamble += "\\usepackage{breakurl}\n";
1761 } else if (features.isRequired("nameref"))
1762 // hyperref loads this automatically
1763 lyxpreamble += "\\usepackage{nameref}\n";
1765 // Will be surrounded by \makeatletter and \makeatother when not empty
1766 docstring atlyxpreamble;
1768 // Some macros LyX will need
1769 docstring tmppreamble(features.getMacros());
1771 if (!tmppreamble.empty())
1772 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1773 "LyX specific LaTeX commands.\n"
1774 + tmppreamble + '\n';
1776 // the text class specific preamble
1777 tmppreamble = features.getTClassPreamble();
1778 if (!tmppreamble.empty())
1779 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1780 "Textclass specific LaTeX commands.\n"
1781 + tmppreamble + '\n';
1783 // suppress date if selected
1784 // use \@ifundefined because we cannot be sure that every document class
1785 // has a \date command
1787 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1789 /* the user-defined preamble */
1790 if (!containsOnly(preamble, " \n\t"))
1792 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1793 "User specified LaTeX commands.\n"
1794 + from_utf8(preamble) + '\n';
1796 // subfig loads internally the LaTeX package "caption". As
1797 // caption is a very popular package, users will load it in
1798 // the preamble. Therefore we must load subfig behind the
1799 // user-defined preamble and check if the caption package was
1800 // loaded or not. For the case that caption is loaded before
1801 // subfig, there is the subfig option "caption=false". This
1802 // option also works when a koma-script class is used and
1803 // koma's own caption commands are used instead of caption. We
1804 // use \PassOptionsToPackage here because the user could have
1805 // already loaded subfig in the preamble.
1806 if (features.isRequired("subfig")) {
1807 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1808 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1809 "\\usepackage{subfig}\n";
1812 // Itemize bullet settings need to be last in case the user
1813 // defines their own bullets that use a package included
1814 // in the user-defined preamble -- ARRae
1815 // Actually it has to be done much later than that
1816 // since some packages like frenchb make modifications
1817 // at \begin{document} time -- JMarc
1818 docstring bullets_def;
1819 for (int i = 0; i < 4; ++i) {
1820 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1821 if (bullets_def.empty())
1822 bullets_def += "\\AtBeginDocument{\n";
1823 bullets_def += " \\def\\labelitemi";
1825 // `i' is one less than the item to modify
1832 bullets_def += "ii";
1838 bullets_def += '{' +
1839 user_defined_bullet(i).getText()
1844 if (!bullets_def.empty())
1845 atlyxpreamble += bullets_def + "}\n\n";
1847 if (!atlyxpreamble.empty())
1848 lyxpreamble += "\n\\makeatletter\n"
1849 + atlyxpreamble + "\\makeatother\n\n";
1851 // We try to load babel late, in case it interferes with other packages.
1852 // Jurabib and Hyperref have to be called after babel, though.
1853 if (use_babel && !features.isRequired("jurabib")
1854 && !features.isRequired("hyperref")
1855 && !features.isRequired("vietnamese")
1856 && !features.isRequired("japanese")) {
1858 lyxpreamble += from_utf8(features.getBabelPresettings());
1859 lyxpreamble += from_utf8(babelCall(language_options.str(),
1860 features.needBabelLangOptions())) + '\n';
1861 lyxpreamble += from_utf8(features.getBabelPostsettings());
1864 // xunicode needs to be loaded at least after amsmath, amssymb,
1865 // esint and the other packages that provide special glyphs
1866 if (features.runparams().flavor == OutputParams::XETEX)
1867 lyxpreamble += "\\usepackage{xunicode}\n";
1869 // Polyglossia must be loaded last
1870 if (use_polyglossia) {
1872 lyxpreamble += "\\usepackage{polyglossia}\n";
1873 // set the main language
1874 lyxpreamble += "\\setdefaultlanguage";
1875 if (!language->polyglossiaOpts().empty())
1876 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1877 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1878 // now setup the other languages
1879 std::map<std::string, std::string> const polylangs =
1880 features.getPolyglossiaLanguages();
1881 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1882 mit != polylangs.end() ; ++mit) {
1883 lyxpreamble += "\\setotherlanguage";
1884 if (!mit->second.empty())
1885 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1886 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
1890 docstring const i18npreamble =
1891 features.getTClassI18nPreamble(use_babel, use_polyglossia);
1892 if (!i18npreamble.empty())
1893 lyxpreamble += i18npreamble + '\n';
1901 void BufferParams::useClassDefaults()
1903 DocumentClass const & tclass = documentClass();
1905 sides = tclass.sides();
1906 columns = tclass.columns();
1907 pagestyle = tclass.pagestyle();
1908 use_default_options = true;
1909 // Only if class has a ToC hierarchy
1910 if (tclass.hasTocLevels()) {
1911 secnumdepth = tclass.secnumdepth();
1912 tocdepth = tclass.tocdepth();
1917 bool BufferParams::hasClassDefaults() const
1919 DocumentClass const & tclass = documentClass();
1921 return sides == tclass.sides()
1922 && columns == tclass.columns()
1923 && pagestyle == tclass.pagestyle()
1924 && use_default_options
1925 && secnumdepth == tclass.secnumdepth()
1926 && tocdepth == tclass.tocdepth();
1930 DocumentClass const & BufferParams::documentClass() const
1936 DocumentClass const * BufferParams::documentClassPtr() const
1942 void BufferParams::setDocumentClass(DocumentClass const * const tc)
1944 // evil, but this function is evil
1945 doc_class_ = const_cast<DocumentClass *>(tc);
1949 bool BufferParams::setBaseClass(string const & classname)
1951 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1952 LayoutFileList & bcl = LayoutFileList::get();
1953 if (!bcl.haveClass(classname)) {
1955 bformat(_("The layout file:\n"
1957 "could not be found. A default textclass with default\n"
1958 "layouts will be used. LyX will not be able to produce\n"
1960 from_utf8(classname));
1961 frontend::Alert::error(_("Document class not found"), s);
1962 bcl.addEmptyClass(classname);
1965 bool const success = bcl[classname].load();
1968 bformat(_("Due to some error in it, the layout file:\n"
1970 "could not be loaded. A default textclass with default\n"
1971 "layouts will be used. LyX will not be able to produce\n"
1973 from_utf8(classname));
1974 frontend::Alert::error(_("Could not load class"), s);
1975 bcl.addEmptyClass(classname);
1978 pimpl_->baseClass_ = classname;
1979 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
1984 LayoutFile const * BufferParams::baseClass() const
1986 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1987 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1993 LayoutFileIndex const & BufferParams::baseClassID() const
1995 return pimpl_->baseClass_;
1999 void BufferParams::makeDocumentClass()
2004 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layout_modules_));
2006 if (!local_layout.empty()) {
2007 TextClass::ReturnValues success =
2008 doc_class_->read(local_layout, TextClass::MODULE);
2009 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2010 docstring const msg = _("Error reading internal layout information");
2011 frontend::Alert::warning(_("Read Error"), msg);
2017 bool BufferParams::moduleCanBeAdded(string const & modName) const
2019 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2023 bool BufferParams::addLayoutModule(string const & modName)
2025 LayoutModuleList::const_iterator it = layout_modules_.begin();
2026 LayoutModuleList::const_iterator end = layout_modules_.end();
2027 for (; it != end; it++)
2030 layout_modules_.push_back(modName);
2035 string BufferParams::bufferFormat() const
2037 string format = documentClass().outputFormat();
2038 if (format == "latex") {
2041 if (encoding().package() == Encoding::japanese)
2048 bool BufferParams::isExportable(string const & format) const
2050 vector<string> backs = backends();
2051 for (vector<string>::const_iterator it = backs.begin();
2052 it != backs.end(); ++it)
2053 if (theConverters().isReachable(*it, format))
2060 bool formatSorter(Format const * lhs, Format const * rhs) {
2061 return _(lhs->prettyname()) < _(rhs->prettyname());
2066 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2068 vector<string> const backs = backends();
2069 set<string> excludes;
2070 if (useNonTeXFonts) {
2071 excludes.insert("latex");
2072 excludes.insert("pdflatex");
2074 vector<Format const *> result =
2075 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2076 for (vector<string>::const_iterator it = backs.begin() + 1;
2077 it != backs.end(); ++it) {
2078 vector<Format const *> r =
2079 theConverters().getReachable(*it, only_viewable, false, excludes);
2080 result.insert(result.end(), r.begin(), r.end());
2082 sort(result.begin(), result.end(), formatSorter);
2087 bool BufferParams::isExportableFormat(string const & format) const
2089 typedef vector<Format const *> Formats;
2091 formats = exportableFormats(true);
2092 Formats::const_iterator fit = formats.begin();
2093 Formats::const_iterator end = formats.end();
2094 for (; fit != end ; ++fit) {
2095 if ((*fit)->name() == format)
2102 vector<string> BufferParams::backends() const
2105 v.push_back(bufferFormat());
2106 // FIXME: Don't hardcode format names here, but use a flag
2107 if (v.back() == "latex") {
2108 v.push_back("pdflatex");
2109 v.push_back("luatex");
2110 v.push_back("dviluatex");
2111 v.push_back("xetex");
2112 } else if (v.back() == "xetex") {
2113 v.push_back("luatex");
2114 v.push_back("dviluatex");
2116 v.push_back("xhtml");
2117 v.push_back("text");
2123 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const format) const
2125 string const dformat = (format.empty() || format == "default") ?
2126 getDefaultOutputFormat() : format;
2127 DefaultFlavorCache::const_iterator it =
2128 default_flavors_.find(dformat);
2130 if (it != default_flavors_.end())
2133 OutputParams::FLAVOR result = OutputParams::LATEX;
2135 if (dformat == "xhtml")
2136 result = OutputParams::HTML;
2138 // Try to determine flavor of default output format
2139 vector<string> backs = backends();
2140 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2141 // Get shortest path to format
2142 Graph::EdgePath path;
2143 for (vector<string>::const_iterator it = backs.begin();
2144 it != backs.end(); ++it) {
2145 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2146 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2151 result = theConverters().getFlavor(path);
2154 // cache this flavor
2155 default_flavors_[dformat] = result;
2160 string BufferParams::getDefaultOutputFormat() const
2162 if (!default_output_format.empty()
2163 && default_output_format != "default")
2164 return default_output_format;
2167 || encoding().package() == Encoding::japanese) {
2168 vector<Format const *> const formats = exportableFormats(true);
2169 if (formats.empty())
2171 // return the first we find
2172 return formats.front()->name();
2174 return lyxrc.default_view_format;
2177 Font const BufferParams::getFont() const
2179 FontInfo f = documentClass().defaultfont();
2180 if (fonts_default_family == "rmdefault")
2181 f.setFamily(ROMAN_FAMILY);
2182 else if (fonts_default_family == "sfdefault")
2183 f.setFamily(SANS_FAMILY);
2184 else if (fonts_default_family == "ttdefault")
2185 f.setFamily(TYPEWRITER_FAMILY);
2186 return Font(f, language);
2190 bool BufferParams::isLatex() const
2192 return documentClass().outputType() == LATEX;
2196 bool BufferParams::isLiterate() const
2198 return documentClass().outputType() == LITERATE;
2202 bool BufferParams::isDocBook() const
2204 return documentClass().outputType() == DOCBOOK;
2208 void BufferParams::readPreamble(Lexer & lex)
2210 if (lex.getString() != "\\begin_preamble")
2211 lyxerr << "Error (BufferParams::readPreamble):"
2212 "consistency check failed." << endl;
2214 preamble = lex.getLongString("\\end_preamble");
2218 void BufferParams::readLocalLayout(Lexer & lex)
2220 if (lex.getString() != "\\begin_local_layout")
2221 lyxerr << "Error (BufferParams::readLocalLayout):"
2222 "consistency check failed." << endl;
2224 local_layout = lex.getLongString("\\end_local_layout");
2228 bool BufferParams::setLanguage(string const & lang)
2230 Language const *new_language = languages.getLanguage(lang);
2231 if (!new_language) {
2232 // Language lang was not found
2235 language = new_language;
2240 void BufferParams::readLanguage(Lexer & lex)
2242 if (!lex.next()) return;
2244 string const tmptok = lex.getString();
2246 // check if tmptok is part of tex_babel in tex-defs.h
2247 if (!setLanguage(tmptok)) {
2248 // Language tmptok was not found
2249 language = default_language;
2250 lyxerr << "Warning: Setting language `"
2251 << tmptok << "' to `" << language->lang()
2257 void BufferParams::readGraphicsDriver(Lexer & lex)
2262 string const tmptok = lex.getString();
2263 // check if tmptok is part of tex_graphics in tex_defs.h
2266 string const test = tex_graphics[n++];
2268 if (test == tmptok) {
2269 graphics_driver = tmptok;
2274 "Warning: graphics driver `$$Token' not recognized!\n"
2275 " Setting graphics driver to `default'.\n");
2276 graphics_driver = "default";
2283 void BufferParams::readBullets(Lexer & lex)
2288 int const index = lex.getInteger();
2290 int temp_int = lex.getInteger();
2291 user_defined_bullet(index).setFont(temp_int);
2292 temp_bullet(index).setFont(temp_int);
2294 user_defined_bullet(index).setCharacter(temp_int);
2295 temp_bullet(index).setCharacter(temp_int);
2297 user_defined_bullet(index).setSize(temp_int);
2298 temp_bullet(index).setSize(temp_int);
2302 void BufferParams::readBulletsLaTeX(Lexer & lex)
2304 // The bullet class should be able to read this.
2307 int const index = lex.getInteger();
2309 docstring const temp_str = lex.getDocString();
2311 user_defined_bullet(index).setText(temp_str);
2312 temp_bullet(index).setText(temp_str);
2316 void BufferParams::readModules(Lexer & lex)
2318 if (!lex.eatLine()) {
2319 lyxerr << "Error (BufferParams::readModules):"
2320 "Unexpected end of input." << endl;
2324 string mod = lex.getString();
2325 if (mod == "\\end_modules")
2327 addLayoutModule(mod);
2333 void BufferParams::readRemovedModules(Lexer & lex)
2335 if (!lex.eatLine()) {
2336 lyxerr << "Error (BufferParams::readRemovedModules):"
2337 "Unexpected end of input." << endl;
2341 string mod = lex.getString();
2342 if (mod == "\\end_removed_modules")
2344 removed_modules_.push_back(mod);
2347 // now we want to remove any removed modules that were previously
2348 // added. normally, that will be because default modules were added in
2349 // setBaseClass(), which gets called when \textclass is read at the
2350 // start of the read.
2351 list<string>::const_iterator rit = removed_modules_.begin();
2352 list<string>::const_iterator const ren = removed_modules_.end();
2353 for (; rit != ren; rit++) {
2354 LayoutModuleList::iterator const mit = layout_modules_.begin();
2355 LayoutModuleList::iterator const men = layout_modules_.end();
2356 LayoutModuleList::iterator found = find(mit, men, *rit);
2359 layout_modules_.erase(found);
2364 void BufferParams::readIncludeonly(Lexer & lex)
2366 if (!lex.eatLine()) {
2367 lyxerr << "Error (BufferParams::readIncludeonly):"
2368 "Unexpected end of input." << endl;
2372 string child = lex.getString();
2373 if (child == "\\end_includeonly")
2375 included_children_.push_back(child);
2381 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2383 switch (papersize) {
2385 // could be anything, so don't guess
2387 case PAPER_CUSTOM: {
2388 if (purpose == XDVI && !paperwidth.empty() &&
2389 !paperheight.empty()) {
2390 // heightxwidth<unit>
2391 string first = paperwidth;
2392 string second = paperheight;
2393 if (orientation == ORIENTATION_LANDSCAPE)
2396 return first.erase(first.length() - 2)
2402 // dvips and dvipdfm do not know this
2403 if (purpose == DVIPS || purpose == DVIPDFM)
2407 if (purpose == DVIPS || purpose == DVIPDFM)
2411 if (purpose == DVIPS || purpose == DVIPDFM)
2421 if (purpose == DVIPS || purpose == DVIPDFM)
2425 if (purpose == DVIPS || purpose == DVIPDFM)
2429 if (purpose == DVIPS || purpose == DVIPDFM)
2433 if (purpose == DVIPS || purpose == DVIPDFM)
2437 if (purpose == DVIPS || purpose == DVIPDFM)
2441 // dvipdfm does not know this
2442 if (purpose == DVIPDFM)
2446 if (purpose == DVIPDFM)
2450 if (purpose == DVIPS || purpose == DVIPDFM)
2454 if (purpose == DVIPS || purpose == DVIPDFM)
2458 if (purpose == DVIPS || purpose == DVIPDFM)
2462 if (purpose == DVIPS || purpose == DVIPDFM)
2466 if (purpose == DVIPS || purpose == DVIPDFM)
2470 if (purpose == DVIPS || purpose == DVIPDFM)
2474 if (purpose == DVIPS || purpose == DVIPDFM)
2478 if (purpose == DVIPS || purpose == DVIPDFM)
2482 if (purpose == DVIPS || purpose == DVIPDFM)
2486 if (purpose == DVIPS || purpose == DVIPDFM)
2490 if (purpose == DVIPS || purpose == DVIPDFM)
2494 if (purpose == DVIPS || purpose == DVIPDFM)
2498 if (purpose == DVIPS || purpose == DVIPDFM)
2502 if (purpose == DVIPS || purpose == DVIPDFM)
2506 if (purpose == DVIPS || purpose == DVIPDFM)
2509 case PAPER_USEXECUTIVE:
2510 // dvipdfm does not know this
2511 if (purpose == DVIPDFM)
2516 case PAPER_USLETTER:
2518 if (purpose == XDVI)
2525 string const BufferParams::dvips_options() const
2529 // If the class loads the geometry package, we do not know which
2530 // paper size is used, since we do not set it (bug 7013).
2531 // Therefore we must not specify any argument here.
2532 // dvips gets the correct paper size via DVI specials in this case
2533 // (if the class uses the geometry package correctly).
2534 if (documentClass().provides("geometry"))
2538 && papersize == PAPER_CUSTOM
2539 && !lyxrc.print_paper_dimension_flag.empty()
2540 && !paperwidth.empty()
2541 && !paperheight.empty()) {
2542 // using a custom papersize
2543 result = lyxrc.print_paper_dimension_flag;
2544 result += ' ' + paperwidth;
2545 result += ',' + paperheight;
2547 string const paper_option = paperSizeName(DVIPS);
2548 if (!paper_option.empty() && (paper_option != "letter" ||
2549 orientation != ORIENTATION_LANDSCAPE)) {
2550 // dvips won't accept -t letter -t landscape.
2551 // In all other cases, include the paper size
2553 result = lyxrc.print_paper_flag;
2554 result += ' ' + paper_option;
2557 if (orientation == ORIENTATION_LANDSCAPE &&
2558 papersize != PAPER_CUSTOM)
2559 result += ' ' + lyxrc.print_landscape_flag;
2564 string const BufferParams::font_encoding() const
2566 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2570 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2572 if (lang_package != "auto" && lang_package != "babel"
2573 && lang_package != "default" && lang_package != "none")
2574 return lang_package;
2575 if (lyxrc.language_package_selection == LyXRC::LP_CUSTOM)
2576 return lyxrc.language_custom_package;
2577 // suppress the babel call if there is no BabelName defined
2578 // for the document language in the lib/languages file and if no
2579 // other languages are used (lang_opts is then empty)
2580 if (lang_opts.empty())
2582 // either a specific language (AsBabelOptions setting in
2583 // lib/languages) or the prefs require the languages to
2584 // be submitted to babel itself (not the class).
2586 return "\\usepackage[" + lang_opts + "]{babel}";
2587 return "\\usepackage{babel}";
2591 docstring BufferParams::getGraphicsDriver(string const & package) const
2595 if (package == "geometry") {
2596 if (graphics_driver == "dvips"
2597 || graphics_driver == "dvipdfm"
2598 || graphics_driver == "pdftex"
2599 || graphics_driver == "vtex")
2600 result = from_ascii(graphics_driver);
2601 else if (graphics_driver == "dvipdfmx")
2602 result = from_ascii("dvipdfm");
2609 void BufferParams::writeEncodingPreamble(otexstream & os,
2610 LaTeXFeatures & features) const
2612 // XeTeX does not need this
2613 if (features.runparams().flavor == OutputParams::XETEX)
2615 // LuaTeX neither, but with tex fonts, we need to load
2616 // the luainputenc package.
2617 if (features.runparams().flavor == OutputParams::LUATEX
2618 || features.runparams().flavor == OutputParams::DVILUATEX) {
2619 if (!useNonTeXFonts && inputenc != "default"
2620 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2621 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2622 os << "\\usepackage[utf8]{luainputenc}\n";
2626 if (inputenc == "auto") {
2627 string const doc_encoding =
2628 language->encoding()->latexName();
2629 Encoding::Package const package =
2630 language->encoding()->package();
2632 // Create a list with all the input encodings used
2634 set<string> encodings =
2635 features.getEncodingSet(doc_encoding);
2637 // If the "japanese" package (i.e. pLaTeX) is used,
2638 // inputenc must be omitted.
2639 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2640 if (package == Encoding::japanese)
2641 features.require("japanese");
2643 if ((!encodings.empty() || package == Encoding::inputenc)
2644 && !features.isRequired("japanese")) {
2645 os << "\\usepackage[";
2646 set<string>::const_iterator it = encodings.begin();
2647 set<string>::const_iterator const end = encodings.end();
2649 os << from_ascii(*it);
2652 for (; it != end; ++it)
2653 os << ',' << from_ascii(*it);
2654 if (package == Encoding::inputenc) {
2655 if (!encodings.empty())
2657 os << from_ascii(doc_encoding);
2659 os << "]{inputenc}\n";
2661 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2662 if (language->encoding()->name() == "utf8-cjk"
2663 && LaTeXFeatures::isAvailable("CJKutf8"))
2664 os << "\\usepackage{CJKutf8}\n";
2666 os << "\\usepackage{CJK}\n";
2668 } else if (inputenc != "default") {
2669 switch (encoding().package()) {
2670 case Encoding::none:
2671 case Encoding::japanese:
2673 case Encoding::inputenc:
2674 // do not load inputenc if japanese is used
2675 if (features.isRequired("japanese"))
2677 os << "\\usepackage[" << from_ascii(inputenc)
2681 if (encoding().name() == "utf8-cjk"
2682 && LaTeXFeatures::isAvailable("CJKutf8"))
2683 os << "\\usepackage{CJKutf8}\n";
2685 os << "\\usepackage{CJK}\n";
2690 // The encoding "armscii8" (for Armenian) is only available when
2691 // the package "armtex" is loaded.
2692 if (language->encoding()->latexName() == "armscii8"
2693 || inputenc == "armscii8")
2694 os << "\\usepackage{armtex}\n";
2698 string const BufferParams::parseFontName(string const & name) const
2700 string mangled = name;
2701 size_t const idx = mangled.find('[');
2702 if (idx == string::npos || idx == 0)
2705 return mangled.substr(0, idx - 1);
2709 string const BufferParams::loadFonts(string const & rm,
2710 string const & sf, string const & tt,
2711 bool const & sc, bool const & osf,
2712 int const & sfscale, int const & ttscale,
2713 bool const & use_systemfonts,
2714 LaTeXFeatures & features) const
2716 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2717 several packages have been replaced by others, that might not
2718 be installed on every system. We have to take care for that
2719 (see psnfss.pdf). We try to support all psnfss fonts as well
2720 as the fonts that have become de facto standard in the LaTeX
2721 world (e.g. Latin Modern). We do not support obsolete fonts
2722 (like PSLatex). In general, it should be possible to mix any
2723 rm font with any sf or tt font, respectively. (JSpitzm)
2725 -- separate math fonts.
2728 if (rm == "default" && sf == "default" && tt == "default")
2734 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2735 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2736 * Mapping=tex-text option assures TeX ligatures (such as "--")
2737 * are resolved. Note that tt does not use these ligatures.
2739 * -- add more GUI options?
2740 * -- add more fonts (fonts for other scripts)
2741 * -- if there's a way to find out if a font really supports
2742 * OldStyle, enable/disable the widget accordingly.
2744 if (use_systemfonts && features.isAvailable("fontspec")) {
2745 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2746 // However, until v.2 (2010/07/11) fontspec only knew
2747 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2748 // was introduced for both XeTeX and LuaTeX (LuaTeX
2749 // didn't understand "Mapping=tex-text", while XeTeX
2750 // understood both. With most recent versions, both
2751 // variants are understood by both engines. However,
2752 // we want to provide support for at least TeXLive 2009
2753 // (for XeTeX; LuaTeX is only supported as of v.2)
2754 string const texmapping =
2755 (features.runparams().flavor == OutputParams::XETEX) ?
2756 "Mapping=tex-text" : "Ligatures=TeX";
2757 if (rm != "default") {
2758 os << "\\setmainfont[" << texmapping;
2760 os << ",Numbers=OldStyle";
2761 os << "]{" << parseFontName(rm) << "}\n";
2763 if (sf != "default") {
2764 string const sans = parseFontName(sf);
2766 os << "\\setsansfont[Scale="
2767 << float(sfscale) / 100
2768 << "," << texmapping << "]{"
2771 os << "\\setsansfont[" << texmapping << "]{"
2774 if (tt != "default") {
2775 string const mono = parseFontName(tt);
2777 os << "\\setmonofont[Scale="
2778 << float(ttscale) / 100
2782 os << "\\setmonofont{"
2789 // Computer Modern (must be explicitly selectable -- there might be classes
2790 // that define a different default font!
2792 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2793 // osf for Computer Modern needs eco.sty
2795 os << "\\usepackage{eco}\n";
2797 // Latin Modern Roman
2798 else if (rm == "lmodern")
2799 os << "\\usepackage{lmodern}\n";
2801 else if (rm == "ae") {
2802 // not needed when using OT1 font encoding.
2803 if (font_encoding() != "default")
2804 os << "\\usepackage{ae,aecompl}\n";
2807 else if (rm == "times") {
2808 // try to load the best available package
2809 if (LaTeXFeatures::isAvailable("mathptmx"))
2810 os << "\\usepackage{mathptmx}\n";
2811 else if (LaTeXFeatures::isAvailable("mathptm"))
2812 os << "\\usepackage{mathptm}\n";
2814 os << "\\usepackage{times}\n";
2817 else if (rm == "palatino") {
2818 // try to load the best available package
2819 if (LaTeXFeatures::isAvailable("mathpazo")) {
2820 os << "\\usepackage";
2826 // "osf" includes "sc"!
2830 os << "{mathpazo}\n";
2832 else if (LaTeXFeatures::isAvailable("mathpple"))
2833 os << "\\usepackage{mathpple}\n";
2835 os << "\\usepackage{palatino}\n";
2838 else if (rm == "utopia") {
2839 // fourier supersedes utopia.sty, but does
2840 // not work with OT1 encoding.
2841 if (LaTeXFeatures::isAvailable("fourier")
2842 && font_encoding() != "default") {
2843 os << "\\usepackage";
2854 os << "{fourier}\n";
2857 os << "\\usepackage{utopia}\n";
2859 // Bera (complete fontset)
2860 else if (rm == "bera" && sf == "default" && tt == "default")
2861 os << "\\usepackage{bera}\n";
2863 else if (rm != "default")
2864 os << "\\usepackage" << "{" << rm << "}\n";
2867 // Helvetica, Bera Sans
2868 if (sf == "helvet" || sf == "berasans") {
2870 os << "\\usepackage[scaled=" << float(sfscale) / 100
2871 << "]{" << sf << "}\n";
2873 os << "\\usepackage{" << sf << "}\n";
2876 else if (sf == "avant")
2877 os << "\\usepackage{" << sf << "}\n";
2878 // Computer Modern, Latin Modern, CM Bright
2879 else if (sf != "default")
2880 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2882 // monospaced/typewriter
2883 // Courier, LuxiMono
2884 if (tt == "luximono" || tt == "beramono") {
2886 os << "\\usepackage[scaled=" << float(ttscale) / 100
2887 << "]{" << tt << "}\n";
2889 os << "\\usepackage{" << tt << "}\n";
2892 else if (tt == "courier" )
2893 os << "\\usepackage{" << tt << "}\n";
2894 // Computer Modern, Latin Modern, CM Bright
2895 else if (tt != "default")
2896 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2902 Encoding const & BufferParams::encoding() const
2904 // FIXME: actually, we should check for the flavor
2905 // or runparams.isFullyUnicode() here:
2906 // This check will not work with XeTeX/LuaTeX and tex fonts.
2907 // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2909 return *(encodings.fromLaTeXName("utf8-plain"));
2910 if (inputenc == "auto" || inputenc == "default")
2911 return *language->encoding();
2912 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2915 LYXERR0("Unknown inputenc value `" << inputenc
2916 << "'. Using `auto' instead.");
2917 return *language->encoding();
2921 CiteEngine BufferParams::citeEngine() const
2923 // FIXME the class should provide the numerical/
2924 // authoryear choice
2925 if (documentClass().provides("natbib")
2926 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2927 return ENGINE_NATBIB_AUTHORYEAR;
2928 return cite_engine_;
2932 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2934 cite_engine_ = cite_engine;