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 use_amsmath = package_auto;
365 use_esint = package_auto;
366 use_mhchem = package_auto;
367 use_mathdots = package_auto;
368 use_undertilde = package_auto;
369 cite_engine_ = ENGINE_BASIC;
370 use_bibtopic = false;
372 trackChanges = false;
373 outputChanges = false;
374 use_default_options = true;
375 maintain_unincluded_children = false;
378 language = default_language;
380 fonts_roman = "default";
381 fonts_sans = "default";
382 fonts_typewriter = "default";
383 fonts_default_family = "default";
384 useNonTeXFonts = false;
385 fonts_expert_sc = false;
386 fonts_old_figures = false;
387 fonts_sans_scale = 100;
388 fonts_typewriter_scale = 100;
390 lang_package = "default";
391 graphics_driver = "default";
392 default_output_format = "default";
393 bibtex_command = "default";
394 index_command = "default";
397 listings_params = string();
398 pagestyle = "default";
399 suppress_date = false;
400 // no color is the default (white)
401 backgroundcolor = lyx::rgbFromHexName("#ffffff");
402 isbackgroundcolor = false;
403 // no color is the default (black)
404 fontcolor = lyx::rgbFromHexName("#000000");
406 // light gray is the default font color for greyed-out notes
407 notefontcolor = lyx::rgbFromHexName("#cccccc");
408 boxbgcolor = lyx::rgbFromHexName("#ff0000");
409 compressed = lyxrc.save_compressed;
410 for (int iter = 0; iter < 4; ++iter) {
411 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
412 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
415 indiceslist().addDefault(B_("Index"));
416 html_be_strict = false;
417 html_math_output = MathML;
418 html_math_img_scale = 1.0;
419 html_css_as_file = false;
426 docstring BufferParams::B_(string const & l10n) const
428 LASSERT(language, /**/);
429 return getMessages(language->code()).get(l10n);
433 AuthorList & BufferParams::authors()
435 return pimpl_->authorlist;
439 AuthorList const & BufferParams::authors() const
441 return pimpl_->authorlist;
445 BranchList & BufferParams::branchlist()
447 return pimpl_->branchlist;
451 BranchList const & BufferParams::branchlist() const
453 return pimpl_->branchlist;
457 IndicesList & BufferParams::indiceslist()
459 return pimpl_->indiceslist;
463 IndicesList const & BufferParams::indiceslist() const
465 return pimpl_->indiceslist;
469 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
471 LASSERT(index < 4, /**/);
472 return pimpl_->temp_bullets[index];
476 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
478 LASSERT(index < 4, /**/);
479 return pimpl_->temp_bullets[index];
483 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
485 LASSERT(index < 4, /**/);
486 return pimpl_->user_defined_bullets[index];
490 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
492 LASSERT(index < 4, /**/);
493 return pimpl_->user_defined_bullets[index];
497 Spacing & BufferParams::spacing()
499 return pimpl_->spacing;
503 Spacing const & BufferParams::spacing() const
505 return pimpl_->spacing;
509 PDFOptions & BufferParams::pdfoptions()
511 return pimpl_->pdfoptions;
515 PDFOptions const & BufferParams::pdfoptions() const
517 return pimpl_->pdfoptions;
521 HSpace const & BufferParams::getIndentation() const
523 return pimpl_->indentation;
527 void BufferParams::setIndentation(HSpace const & indent)
529 pimpl_->indentation = indent;
533 VSpace const & BufferParams::getDefSkip() const
535 return pimpl_->defskip;
539 void BufferParams::setDefSkip(VSpace const & vs)
541 // DEFSKIP will cause an infinite loop
542 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
543 pimpl_->defskip = vs;
547 string BufferParams::readToken(Lexer & lex, string const & token,
548 FileName const & filepath)
550 if (token == "\\textclass") {
552 string const classname = lex.getString();
553 // if there exists a local layout file, ignore the system one
554 // NOTE: in this case, the textclass (.cls file) is assumed to
557 LayoutFileList & bcl = LayoutFileList::get();
558 if (tcp.empty() && !filepath.empty())
559 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
563 setBaseClass(classname);
564 // We assume that a tex class exists for local or unknown
565 // layouts so this warning, will only be given for system layouts.
566 if (!baseClass()->isTeXClassAvailable()) {
567 docstring const desc =
568 translateIfPossible(from_utf8(baseClass()->description()));
569 docstring const prereqs =
570 from_utf8(baseClass()->prerequisites());
571 docstring const msg =
572 bformat(_("The selected document class\n"
574 "requires external files that are not available.\n"
575 "The document class can still be used, but the\n"
576 "document cannot be compiled until the following\n"
577 "prerequisites are installed:\n"
579 "See section 3.1.2.2 (Class Availability) of the\n"
580 "User's Guide for more information."), desc, prereqs);
581 frontend::Alert::warning(_("Document class not available"),
584 } else if (token == "\\begin_preamble") {
586 } else if (token == "\\begin_local_layout") {
587 readLocalLayout(lex);
588 } else if (token == "\\begin_modules") {
590 } else if (token == "\\begin_removed_modules") {
591 readRemovedModules(lex);
592 } else if (token == "\\begin_includeonly") {
593 readIncludeonly(lex);
594 } else if (token == "\\maintain_unincluded_children") {
595 lex >> maintain_unincluded_children;
596 } else if (token == "\\options") {
598 options = lex.getString();
599 } else if (token == "\\use_default_options") {
600 lex >> use_default_options;
601 } else if (token == "\\master") {
603 master = lex.getString();
604 } else if (token == "\\suppress_date") {
605 lex >> suppress_date;
606 } else if (token == "\\language") {
608 } else if (token == "\\language_package") {
610 lang_package = lex.getString();
611 } else if (token == "\\inputencoding") {
613 } else if (token == "\\graphics") {
614 readGraphicsDriver(lex);
615 } else if (token == "\\default_output_format") {
616 lex >> default_output_format;
617 } else if (token == "\\bibtex_command") {
619 bibtex_command = lex.getString();
620 } else if (token == "\\index_command") {
622 index_command = lex.getString();
623 } else if (token == "\\fontencoding") {
625 fontenc = lex.getString();
626 } else if (token == "\\font_roman") {
628 fonts_roman = lex.getString();
629 } else if (token == "\\font_sans") {
631 fonts_sans = lex.getString();
632 } else if (token == "\\font_typewriter") {
634 fonts_typewriter = lex.getString();
635 } else if (token == "\\font_default_family") {
636 lex >> fonts_default_family;
637 } else if (token == "\\use_non_tex_fonts") {
638 lex >> useNonTeXFonts;
639 } else if (token == "\\font_sc") {
640 lex >> fonts_expert_sc;
641 } else if (token == "\\font_osf") {
642 lex >> fonts_old_figures;
643 } else if (token == "\\font_sf_scale") {
644 lex >> fonts_sans_scale;
645 } else if (token == "\\font_tt_scale") {
646 lex >> fonts_typewriter_scale;
647 } else if (token == "\\font_cjk") {
649 } else if (token == "\\paragraph_separation") {
652 paragraph_separation = parseptranslator().find(parsep);
653 } else if (token == "\\paragraph_indentation") {
655 string indentation = lex.getString();
656 pimpl_->indentation = HSpace(indentation);
657 } else if (token == "\\defskip") {
659 string const defskip = lex.getString();
660 pimpl_->defskip = VSpace(defskip);
661 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
663 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
664 } else if (token == "\\quotes_language") {
667 quotes_language = quoteslangtranslator().find(quotes_lang);
668 } else if (token == "\\papersize") {
671 papersize = papersizetranslator().find(ppsize);
672 } else if (token == "\\use_geometry") {
674 } else if (token == "\\use_amsmath") {
677 use_amsmath = packagetranslator().find(use_ams);
678 } else if (token == "\\use_esint") {
681 use_esint = packagetranslator().find(useesint);
682 } else if (token == "\\use_mhchem") {
685 use_mhchem = packagetranslator().find(usemhchem);
686 } else if (token == "\\use_mathdots") {
689 use_mathdots = packagetranslator().find(usemathdots);
690 } else if (token == "\\use_undertilde") {
692 lex >> useundertilde;
693 use_undertilde = packagetranslator().find(useundertilde);
694 } else if (token == "\\cite_engine") {
697 cite_engine_ = citeenginetranslator().find(engine);
698 } else if (token == "\\use_bibtopic") {
700 } else if (token == "\\use_indices") {
702 } else if (token == "\\tracking_changes") {
704 } else if (token == "\\output_changes") {
705 lex >> outputChanges;
706 } else if (token == "\\branch") {
708 docstring branch = lex.getDocString();
709 branchlist().add(branch);
712 string const tok = lex.getString();
713 if (tok == "\\end_branch")
715 Branch * branch_ptr = branchlist().find(branch);
716 if (tok == "\\selected") {
719 branch_ptr->setSelected(lex.getInteger());
721 if (tok == "\\filename_suffix") {
724 branch_ptr->setFileNameSuffix(lex.getInteger());
726 if (tok == "\\color") {
728 string color = lex.getString();
730 branch_ptr->setColor(color);
731 // Update also the Color table:
733 color = lcolor.getX11Name(Color_background);
735 lcolor.setColor(to_utf8(branch), color);
738 } else if (token == "\\index") {
740 docstring index = lex.getDocString();
742 indiceslist().add(index);
745 string const tok = lex.getString();
746 if (tok == "\\end_index")
748 Index * index_ptr = indiceslist().find(index);
749 if (tok == "\\shortcut") {
751 shortcut = lex.getDocString();
753 index_ptr->setShortcut(shortcut);
755 if (tok == "\\color") {
757 string color = lex.getString();
759 index_ptr->setColor(color);
760 // Update also the Color table:
762 color = lcolor.getX11Name(Color_background);
764 if (!shortcut.empty())
765 lcolor.setColor(to_utf8(shortcut), color);
768 } else if (token == "\\author") {
770 istringstream ss(lex.getString());
773 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
774 } else if (token == "\\paperorientation") {
777 orientation = paperorientationtranslator().find(orient);
778 } else if (token == "\\backgroundcolor") {
780 backgroundcolor = lyx::rgbFromHexName(lex.getString());
781 isbackgroundcolor = true;
782 } else if (token == "\\fontcolor") {
784 fontcolor = lyx::rgbFromHexName(lex.getString());
786 } else if (token == "\\notefontcolor") {
788 string color = lex.getString();
789 notefontcolor = lyx::rgbFromHexName(color);
790 } else if (token == "\\boxbgcolor") {
792 string color = lex.getString();
793 boxbgcolor = lyx::rgbFromHexName(color);
794 } else if (token == "\\paperwidth") {
796 } else if (token == "\\paperheight") {
798 } else if (token == "\\leftmargin") {
800 } else if (token == "\\topmargin") {
802 } else if (token == "\\rightmargin") {
804 } else if (token == "\\bottommargin") {
806 } else if (token == "\\headheight") {
808 } else if (token == "\\headsep") {
810 } else if (token == "\\footskip") {
812 } else if (token == "\\columnsep") {
814 } else if (token == "\\paperfontsize") {
816 } else if (token == "\\papercolumns") {
818 } else if (token == "\\listings_params") {
821 listings_params = InsetListingsParams(par).params();
822 } else if (token == "\\papersides") {
825 sides = sidestranslator().find(psides);
826 } else if (token == "\\paperpagestyle") {
828 } else if (token == "\\bullet") {
830 } else if (token == "\\bulletLaTeX") {
831 readBulletsLaTeX(lex);
832 } else if (token == "\\secnumdepth") {
834 } else if (token == "\\tocdepth") {
836 } else if (token == "\\spacing") {
840 if (nspacing == "other") {
843 spacing().set(spacetranslator().find(nspacing), tmp_val);
844 } else if (token == "\\float_placement") {
845 lex >> float_placement;
847 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
848 string toktmp = pdfoptions().readToken(lex, token);
849 if (!toktmp.empty()) {
850 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
854 } else if (token == "\\html_math_output") {
857 html_math_output = static_cast<MathOutput>(temp);
858 } else if (token == "\\html_be_strict") {
859 lex >> html_be_strict;
860 } else if (token == "\\html_css_as_file") {
861 lex >> html_css_as_file;
862 } else if (token == "\\html_math_img_scale") {
863 lex >> html_math_img_scale;
864 } else if (token == "\\html_latex_start") {
866 html_latex_start = lex.getString();
867 } else if (token == "\\html_latex_end") {
869 html_latex_end = lex.getString();
870 } else if (token == "\\output_sync") {
872 } else if (token == "\\output_sync_macro") {
873 lex >> output_sync_macro;
874 } else if (token == "\\use_refstyle") {
877 lyxerr << "BufferParams::readToken(): Unknown token: " <<
886 void BufferParams::writeFile(ostream & os) const
888 // The top of the file is written by the buffer.
889 // Prints out the buffer info into the .lyx file given by file
892 os << "\\textclass " << baseClass()->name() << '\n';
895 if (!preamble.empty()) {
896 // remove '\n' from the end of preamble
897 string const tmppreamble = rtrim(preamble, "\n");
898 os << "\\begin_preamble\n"
900 << "\n\\end_preamble\n";
904 if (!options.empty()) {
905 os << "\\options " << options << '\n';
908 // use the class options defined in the layout?
909 os << "\\use_default_options "
910 << convert<string>(use_default_options) << "\n";
912 // the master document
913 if (!master.empty()) {
914 os << "\\master " << master << '\n';
918 if (!removed_modules_.empty()) {
919 os << "\\begin_removed_modules" << '\n';
920 list<string>::const_iterator it = removed_modules_.begin();
921 list<string>::const_iterator en = removed_modules_.end();
922 for (; it != en; it++)
924 os << "\\end_removed_modules" << '\n';
928 if (!layout_modules_.empty()) {
929 os << "\\begin_modules" << '\n';
930 LayoutModuleList::const_iterator it = layout_modules_.begin();
931 LayoutModuleList::const_iterator en = layout_modules_.end();
932 for (; it != en; it++)
934 os << "\\end_modules" << '\n';
938 if (!included_children_.empty()) {
939 os << "\\begin_includeonly" << '\n';
940 list<string>::const_iterator it = included_children_.begin();
941 list<string>::const_iterator en = included_children_.end();
942 for (; it != en; it++)
944 os << "\\end_includeonly" << '\n';
946 os << "\\maintain_unincluded_children "
947 << convert<string>(maintain_unincluded_children) << '\n';
949 // local layout information
950 if (!local_layout.empty()) {
951 // remove '\n' from the end
952 string const tmplocal = rtrim(local_layout, "\n");
953 os << "\\begin_local_layout\n"
955 << "\n\\end_local_layout\n";
958 // then the text parameters
959 if (language != ignore_language)
960 os << "\\language " << language->lang() << '\n';
961 os << "\\language_package " << lang_package
962 << "\n\\inputencoding " << inputenc
963 << "\n\\fontencoding " << fontenc
964 << "\n\\font_roman " << fonts_roman
965 << "\n\\font_sans " << fonts_sans
966 << "\n\\font_typewriter " << fonts_typewriter
967 << "\n\\font_default_family " << fonts_default_family
968 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
969 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
970 << "\n\\font_osf " << convert<string>(fonts_old_figures)
971 << "\n\\font_sf_scale " << fonts_sans_scale
972 << "\n\\font_tt_scale " << fonts_typewriter_scale
974 if (!fonts_cjk.empty()) {
975 os << "\\font_cjk " << fonts_cjk << '\n';
977 os << "\n\\graphics " << graphics_driver << '\n';
978 os << "\\default_output_format " << default_output_format << '\n';
979 os << "\\output_sync " << output_sync << '\n';
980 if (!output_sync_macro.empty())
981 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
982 os << "\\bibtex_command " << bibtex_command << '\n';
983 os << "\\index_command " << index_command << '\n';
985 if (!float_placement.empty()) {
986 os << "\\float_placement " << float_placement << '\n';
988 os << "\\paperfontsize " << fontsize << '\n';
990 spacing().writeFile(os);
991 pdfoptions().writeFile(os);
993 os << "\\papersize " << string_papersize[papersize]
994 << "\n\\use_geometry " << convert<string>(use_geometry)
995 << "\n\\use_amsmath " << use_amsmath
996 << "\n\\use_esint " << use_esint
997 << "\n\\use_mhchem " << use_mhchem
998 << "\n\\use_mathdots " << use_mathdots
999 << "\n\\use_undertilde " << use_undertilde
1000 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
1001 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1002 << "\n\\use_indices " << convert<string>(use_indices)
1003 << "\n\\paperorientation " << string_orientation[orientation]
1004 << "\n\\suppress_date " << convert<string>(suppress_date)
1005 << "\n\\use_refstyle " << use_refstyle
1007 if (isbackgroundcolor == true)
1008 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1009 if (isfontcolor == true)
1010 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1011 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1012 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1013 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1014 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1016 BranchList::const_iterator it = branchlist().begin();
1017 BranchList::const_iterator end = branchlist().end();
1018 for (; it != end; ++it) {
1019 os << "\\branch " << to_utf8(it->branch())
1020 << "\n\\selected " << it->isSelected()
1021 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1022 << "\n\\color " << lyx::X11hexname(it->color())
1027 IndicesList::const_iterator iit = indiceslist().begin();
1028 IndicesList::const_iterator iend = indiceslist().end();
1029 for (; iit != iend; ++iit) {
1030 os << "\\index " << to_utf8(iit->index())
1031 << "\n\\shortcut " << to_utf8(iit->shortcut())
1032 << "\n\\color " << lyx::X11hexname(iit->color())
1037 if (!paperwidth.empty())
1038 os << "\\paperwidth "
1039 << VSpace(paperwidth).asLyXCommand() << '\n';
1040 if (!paperheight.empty())
1041 os << "\\paperheight "
1042 << VSpace(paperheight).asLyXCommand() << '\n';
1043 if (!leftmargin.empty())
1044 os << "\\leftmargin "
1045 << VSpace(leftmargin).asLyXCommand() << '\n';
1046 if (!topmargin.empty())
1047 os << "\\topmargin "
1048 << VSpace(topmargin).asLyXCommand() << '\n';
1049 if (!rightmargin.empty())
1050 os << "\\rightmargin "
1051 << VSpace(rightmargin).asLyXCommand() << '\n';
1052 if (!bottommargin.empty())
1053 os << "\\bottommargin "
1054 << VSpace(bottommargin).asLyXCommand() << '\n';
1055 if (!headheight.empty())
1056 os << "\\headheight "
1057 << VSpace(headheight).asLyXCommand() << '\n';
1058 if (!headsep.empty())
1060 << VSpace(headsep).asLyXCommand() << '\n';
1061 if (!footskip.empty())
1063 << VSpace(footskip).asLyXCommand() << '\n';
1064 if (!columnsep.empty())
1065 os << "\\columnsep "
1066 << VSpace(columnsep).asLyXCommand() << '\n';
1067 os << "\\secnumdepth " << secnumdepth
1068 << "\n\\tocdepth " << tocdepth
1069 << "\n\\paragraph_separation "
1070 << string_paragraph_separation[paragraph_separation];
1071 if (!paragraph_separation)
1072 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1074 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1075 os << "\n\\quotes_language "
1076 << string_quotes_language[quotes_language]
1077 << "\n\\papercolumns " << columns
1078 << "\n\\papersides " << sides
1079 << "\n\\paperpagestyle " << pagestyle << '\n';
1080 if (!listings_params.empty())
1081 os << "\\listings_params \"" <<
1082 InsetListingsParams(listings_params).encodedString() << "\"\n";
1083 for (int i = 0; i < 4; ++i) {
1084 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1085 if (user_defined_bullet(i).getFont() != -1) {
1086 os << "\\bullet " << i << " "
1087 << user_defined_bullet(i).getFont() << " "
1088 << user_defined_bullet(i).getCharacter() << " "
1089 << user_defined_bullet(i).getSize() << "\n";
1093 os << "\\bulletLaTeX " << i << " \""
1094 << lyx::to_ascii(user_defined_bullet(i).getText())
1100 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1101 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1102 << "\\html_math_output " << html_math_output << '\n'
1103 << "\\html_css_as_file " << html_css_as_file << '\n'
1104 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1106 if (html_math_img_scale != 1.0)
1107 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1108 if (!html_latex_start.empty())
1109 os << "\\html_latex_start " << html_latex_start << '\n';
1110 if (!html_latex_end.empty())
1111 os << "\\html_latex_end " << html_latex_end << '\n';
1113 os << pimpl_->authorlist;
1117 void BufferParams::validate(LaTeXFeatures & features) const
1119 features.require(documentClass().requires());
1121 if (outputChanges) {
1122 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1123 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1124 LaTeXFeatures::isAvailable("xcolor");
1126 switch (features.runparams().flavor) {
1127 case OutputParams::LATEX:
1128 case OutputParams::DVILUATEX:
1130 features.require("ct-dvipost");
1131 features.require("dvipost");
1132 } else if (xcolorulem) {
1133 features.require("ct-xcolor-ulem");
1134 features.require("ulem");
1135 features.require("xcolor");
1137 features.require("ct-none");
1140 case OutputParams::LUATEX:
1141 case OutputParams::PDFLATEX:
1142 case OutputParams::XETEX:
1144 features.require("ct-xcolor-ulem");
1145 features.require("ulem");
1146 features.require("xcolor");
1147 // improves color handling in PDF output
1148 features.require("pdfcolmk");
1150 features.require("ct-none");
1158 // Floats with 'Here definitely' as default setting.
1159 if (float_placement.find('H') != string::npos)
1160 features.require("float");
1162 // AMS Style is at document level
1163 if (use_amsmath == package_on
1164 || documentClass().provides("amsmath"))
1165 features.require("amsmath");
1166 if (use_esint == package_on)
1167 features.require("esint");
1168 if (use_mhchem == package_on)
1169 features.require("mhchem");
1170 if (use_mathdots == package_on)
1171 features.require("mathdots");
1172 if (use_undertilde == package_on)
1173 features.require("undertilde");
1175 // Document-level line spacing
1176 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1177 features.require("setspace");
1179 // the bullet shapes are buffer level not paragraph level
1180 // so they are tested here
1181 for (int i = 0; i < 4; ++i) {
1182 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1184 int const font = user_defined_bullet(i).getFont();
1186 int const c = user_defined_bullet(i).getCharacter();
1192 features.require("latexsym");
1194 } else if (font == 1) {
1195 features.require("amssymb");
1196 } else if (font >= 2 && font <= 5) {
1197 features.require("pifont");
1201 if (pdfoptions().use_hyperref) {
1202 features.require("hyperref");
1203 // due to interferences with babel and hyperref, the color package has to
1204 // be loaded after hyperref when hyperref is used with the colorlinks
1205 // option, see http://www.lyx.org/trac/ticket/5291
1206 if (pdfoptions().colorlinks)
1207 features.require("color");
1210 if (features.runparams().flavor == OutputParams::XETEX
1212 features.require("polyglossia");
1214 if (language->lang() == "vietnamese")
1215 features.require("vietnamese");
1216 else if (language->lang() == "japanese")
1217 features.require("japanese");
1221 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1222 FileName const & filepath) const
1224 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1225 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1226 // \RequirePackage to do so, rather than the normal \usepackage
1227 // Do not try to load any other package before the document class, unless you
1228 // have a thorough understanding of the LATEX internals and know exactly what you
1230 if (features.mustProvide("fix-cm"))
1231 os << "\\RequirePackage{fix-cm}\n";
1233 os << "\\documentclass";
1235 DocumentClass const & tclass = documentClass();
1237 ostringstream clsoptions; // the document class options.
1239 if (tokenPos(tclass.opt_fontsize(),
1240 '|', fontsize) >= 0) {
1241 // only write if existing in list (and not default)
1242 clsoptions << fontsize << "pt,";
1245 // all paper sizes except of A4, A5, B5 and the US sizes need the
1247 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1248 && papersize != PAPER_USLETTER
1249 && papersize != PAPER_USLEGAL
1250 && papersize != PAPER_USEXECUTIVE
1251 && papersize != PAPER_A4
1252 && papersize != PAPER_A5
1253 && papersize != PAPER_B5;
1255 if (!use_geometry) {
1256 switch (papersize) {
1258 clsoptions << "a4paper,";
1260 case PAPER_USLETTER:
1261 clsoptions << "letterpaper,";
1264 clsoptions << "a5paper,";
1267 clsoptions << "b5paper,";
1269 case PAPER_USEXECUTIVE:
1270 clsoptions << "executivepaper,";
1273 clsoptions << "legalpaper,";
1307 if (sides != tclass.sides()) {
1310 clsoptions << "oneside,";
1313 clsoptions << "twoside,";
1319 if (columns != tclass.columns()) {
1321 clsoptions << "twocolumn,";
1323 clsoptions << "onecolumn,";
1327 && orientation == ORIENTATION_LANDSCAPE)
1328 clsoptions << "landscape,";
1330 // language should be a parameter to \documentclass
1331 if (language->babel() == "hebrew"
1332 && default_language->babel() != "hebrew")
1333 // This seems necessary
1334 features.useLanguage(default_language);
1336 ostringstream language_options;
1337 bool const use_babel = features.useBabel() && !tclass.provides("babel");
1338 bool const use_polyglossia = features.usePolyglossia();
1339 bool const global = lyxrc.language_global_options;
1340 if (use_babel || (use_polyglossia && global)) {
1341 language_options << features.getLanguages();
1342 if (!language->babel().empty()) {
1343 if (!language_options.str().empty())
1344 language_options << ',';
1345 language_options << language->babel();
1347 if (global && !features.needBabelLangOptions())
1348 clsoptions << language_options.str() << ',';
1351 // the predefined options from the layout
1352 if (use_default_options && !tclass.options().empty())
1353 clsoptions << tclass.options() << ',';
1355 // the user-defined options
1356 if (!options.empty()) {
1357 clsoptions << options << ',';
1360 string strOptions(clsoptions.str());
1361 if (!strOptions.empty()) {
1362 strOptions = rtrim(strOptions, ",");
1364 os << '[' << from_utf8(strOptions) << ']';
1367 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1368 // end of \documentclass defs
1370 // if we use fontspec, we have to load the AMS packages here
1371 string const ams = features.loadAMSPackages();
1372 if (useNonTeXFonts && !ams.empty())
1373 os << from_ascii(ams);
1376 os << "\\usepackage{fontspec}\n";
1378 // font selection must be done before loading fontenc.sty
1379 string const fonts =
1380 loadFonts(fonts_roman, fonts_sans, fonts_typewriter,
1381 fonts_expert_sc, fonts_old_figures,
1382 fonts_sans_scale, fonts_typewriter_scale,
1383 useNonTeXFonts, features);
1385 os << from_utf8(fonts);
1387 if (fonts_default_family != "default")
1388 os << "\\renewcommand{\\familydefault}{\\"
1389 << from_ascii(fonts_default_family) << "}\n";
1391 // set font encoding
1392 // for arabic_arabi and farsi we also need to load the LAE and
1394 // XeTeX and LuaTeX (with OS fonts) work without fontenc
1395 if (font_encoding() != "default" && language->lang() != "japanese"
1396 && !useNonTeXFonts && !tclass.provides("fontenc")) {
1397 size_t fars = language_options.str().find("farsi");
1398 size_t arab = language_options.str().find("arabic");
1399 if (language->lang() == "arabic_arabi"
1400 || language->lang() == "farsi" || fars != string::npos
1401 || arab != string::npos) {
1402 os << "\\usepackage[" << from_ascii(font_encoding())
1403 << ",LFE,LAE]{fontenc}\n";
1405 os << "\\usepackage[" << from_ascii(font_encoding())
1410 // handle inputenc etc.
1411 writeEncodingPreamble(os, features);
1414 if (!features.runparams().includeall && !included_children_.empty()) {
1415 os << "\\includeonly{";
1416 list<string>::const_iterator it = included_children_.begin();
1417 list<string>::const_iterator en = included_children_.end();
1419 for (; it != en; ++it) {
1420 string incfile = *it;
1421 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1422 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1424 if (!features.runparams().nice)
1426 // \includeonly doesn't want an extension
1427 incfile = changeExtension(incfile, string());
1428 incfile = support::latex_path(incfile);
1429 if (!incfile.empty()) {
1432 os << from_utf8(incfile);
1439 if (!listings_params.empty() || features.isRequired("listings"))
1440 os << "\\usepackage{listings}\n";
1442 if (!listings_params.empty()) {
1444 // do not test validity because listings_params is
1445 // supposed to be valid
1447 InsetListingsParams(listings_params).separatedParams(true);
1448 // we can't support all packages, but we should load the color package
1449 if (par.find("\\color", 0) != string::npos)
1450 features.require("color");
1451 os << from_utf8(par)
1454 if (!tclass.provides("geometry")
1455 && (use_geometry || nonstandard_papersize)) {
1456 odocstringstream ods;
1457 if (!getGraphicsDriver("geometry").empty())
1458 ods << getGraphicsDriver("geometry");
1459 if (orientation == ORIENTATION_LANDSCAPE)
1460 ods << ",landscape";
1461 switch (papersize) {
1463 if (!paperwidth.empty())
1464 ods << ",paperwidth="
1465 << from_ascii(paperwidth);
1466 if (!paperheight.empty())
1467 ods << ",paperheight="
1468 << from_ascii(paperheight);
1470 case PAPER_USLETTER:
1471 ods << ",letterpaper";
1474 ods << ",legalpaper";
1476 case PAPER_USEXECUTIVE:
1477 ods << ",executivepaper";
1564 // default papersize ie PAPER_DEFAULT
1565 switch (lyxrc.default_papersize) {
1566 case PAPER_DEFAULT: // keep compiler happy
1568 case PAPER_USLETTER:
1569 ods << ",letterpaper";
1572 ods << ",legalpaper";
1574 case PAPER_USEXECUTIVE:
1575 ods << ",executivepaper";
1617 docstring const g_options = trim(ods.str(), ",");
1618 os << "\\usepackage";
1619 if (!g_options.empty())
1620 os << '[' << g_options << ']';
1621 os << "{geometry}\n";
1622 // output this only if use_geometry is true
1624 os << "\\geometry{verbose";
1625 if (!topmargin.empty())
1626 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1627 if (!bottommargin.empty())
1628 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1629 if (!leftmargin.empty())
1630 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1631 if (!rightmargin.empty())
1632 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1633 if (!headheight.empty())
1634 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1635 if (!headsep.empty())
1636 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1637 if (!footskip.empty())
1638 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1639 if (!columnsep.empty())
1640 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1643 } else if (orientation == ORIENTATION_LANDSCAPE
1644 || papersize != PAPER_DEFAULT) {
1645 features.require("papersize");
1648 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1649 if (pagestyle == "fancy")
1650 os << "\\usepackage{fancyhdr}\n";
1651 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1654 // only output when the background color is not default
1655 if (isbackgroundcolor == true) {
1656 // only require color here, the background color will be defined
1657 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1659 features.require("color");
1660 features.require("pagecolor");
1663 // only output when the font color is not default
1664 if (isfontcolor == true) {
1665 // only require color here, the font color will be defined
1666 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1668 features.require("color");
1669 features.require("fontcolor");
1672 // Only if class has a ToC hierarchy
1673 if (tclass.hasTocLevels()) {
1674 if (secnumdepth != tclass.secnumdepth()) {
1675 os << "\\setcounter{secnumdepth}{"
1679 if (tocdepth != tclass.tocdepth()) {
1680 os << "\\setcounter{tocdepth}{"
1686 if (paragraph_separation) {
1687 // when skip separation
1688 switch (getDefSkip().kind()) {
1689 case VSpace::SMALLSKIP:
1690 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1692 case VSpace::MEDSKIP:
1693 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1695 case VSpace::BIGSKIP:
1696 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1698 case VSpace::LENGTH:
1699 os << "\\setlength{\\parskip}{"
1700 << from_utf8(getDefSkip().length().asLatexString())
1703 default: // should never happen // Then delete it.
1704 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1707 os << "\\setlength{\\parindent}{0pt}\n";
1709 // when separation by indentation
1710 // only output something when a width is given
1711 if (getIndentation().asLyXCommand() != "default") {
1712 os << "\\setlength{\\parindent}{"
1713 << from_utf8(getIndentation().asLatexCommand())
1718 // Now insert the LyX specific LaTeX commands...
1719 docstring lyxpreamble;
1720 features.resolveAlternatives();
1723 if (!output_sync_macro.empty())
1724 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1725 else if (features.runparams().flavor == OutputParams::LATEX)
1726 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1727 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1728 lyxpreamble += "\\synctex=-1\n";
1731 // due to interferences with babel and hyperref, the color package has to
1732 // be loaded (when it is not already loaded) before babel when hyperref
1733 // is used with the colorlinks option, see
1734 // http://www.lyx.org/trac/ticket/5291
1735 // we decided therefore to load color always before babel, see
1736 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1737 lyxpreamble += from_ascii(features.getColorOptions());
1739 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1741 && (features.isRequired("jurabib")
1742 || features.isRequired("hyperref")
1743 || features.isRequired("vietnamese")
1744 || features.isRequired("japanese"))) {
1746 lyxpreamble += from_utf8(features.getBabelPresettings());
1747 lyxpreamble += from_utf8(babelCall(language_options.str(),
1748 features.needBabelLangOptions())) + '\n';
1749 lyxpreamble += from_utf8(features.getBabelPostsettings());
1752 // The optional packages;
1753 lyxpreamble += from_ascii(features.getPackages());
1755 // Additional Indices
1756 if (features.isRequired("splitidx")) {
1757 IndicesList::const_iterator iit = indiceslist().begin();
1758 IndicesList::const_iterator iend = indiceslist().end();
1759 for (; iit != iend; ++iit) {
1760 lyxpreamble += "\\newindex[";
1761 lyxpreamble += iit->index();
1762 lyxpreamble += "]{";
1763 lyxpreamble += iit->shortcut();
1764 lyxpreamble += "}\n";
1769 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1772 // * Hyperref manual: "Make sure it comes last of your loaded
1773 // packages, to give it a fighting chance of not being over-written,
1774 // since its job is to redefine many LaTeX commands."
1775 // * Email from Heiko Oberdiek: "It is usually better to load babel
1776 // before hyperref. Then hyperref has a chance to detect babel.
1777 // * Has to be loaded before the "LyX specific LaTeX commands" to
1778 // avoid errors with algorithm floats.
1779 // use hyperref explicitly if it is required
1780 if (features.isRequired("hyperref")) {
1781 // pass what we have to stream here, since we need
1782 // to access the stream itself in PDFOptions.
1785 OutputParams tmp_params = features.runparams();
1786 pdfoptions().writeLaTeX(tmp_params, os,
1787 documentClass().provides("hyperref"));
1788 // set back for the rest
1789 lyxpreamble.clear();
1790 // correctly break URLs with hyperref and dvi output
1791 if (features.runparams().flavor == OutputParams::LATEX
1792 && features.isAvailable("breakurl"))
1793 lyxpreamble += "\\usepackage{breakurl}\n";
1794 } else if (features.isRequired("nameref"))
1795 // hyperref loads this automatically
1796 lyxpreamble += "\\usepackage{nameref}\n";
1798 // Will be surrounded by \makeatletter and \makeatother when not empty
1799 docstring atlyxpreamble;
1801 // Some macros LyX will need
1802 docstring tmppreamble(features.getMacros());
1804 if (!tmppreamble.empty())
1805 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1806 "LyX specific LaTeX commands.\n"
1807 + tmppreamble + '\n';
1809 // the text class specific preamble
1810 tmppreamble = features.getTClassPreamble();
1811 if (!tmppreamble.empty())
1812 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1813 "Textclass specific LaTeX commands.\n"
1814 + tmppreamble + '\n';
1816 // suppress date if selected
1817 // use \@ifundefined because we cannot be sure that every document class
1818 // has a \date command
1820 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1822 /* the user-defined preamble */
1823 if (!containsOnly(preamble, " \n\t"))
1825 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1826 "User specified LaTeX commands.\n"
1827 + from_utf8(preamble) + '\n';
1829 // subfig loads internally the LaTeX package "caption". As
1830 // caption is a very popular package, users will load it in
1831 // the preamble. Therefore we must load subfig behind the
1832 // user-defined preamble and check if the caption package was
1833 // loaded or not. For the case that caption is loaded before
1834 // subfig, there is the subfig option "caption=false". This
1835 // option also works when a koma-script class is used and
1836 // koma's own caption commands are used instead of caption. We
1837 // use \PassOptionsToPackage here because the user could have
1838 // already loaded subfig in the preamble.
1839 if (features.isRequired("subfig")) {
1840 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1841 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1842 "\\usepackage{subfig}\n";
1845 // Itemize bullet settings need to be last in case the user
1846 // defines their own bullets that use a package included
1847 // in the user-defined preamble -- ARRae
1848 // Actually it has to be done much later than that
1849 // since some packages like frenchb make modifications
1850 // at \begin{document} time -- JMarc
1851 docstring bullets_def;
1852 for (int i = 0; i < 4; ++i) {
1853 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1854 if (bullets_def.empty())
1855 bullets_def += "\\AtBeginDocument{\n";
1856 bullets_def += " \\def\\labelitemi";
1858 // `i' is one less than the item to modify
1865 bullets_def += "ii";
1871 bullets_def += '{' +
1872 user_defined_bullet(i).getText()
1877 if (!bullets_def.empty())
1878 atlyxpreamble += bullets_def + "}\n\n";
1880 if (!atlyxpreamble.empty())
1881 lyxpreamble += "\n\\makeatletter\n"
1882 + atlyxpreamble + "\\makeatother\n\n";
1884 // We try to load babel late, in case it interferes with other packages.
1885 // Jurabib and Hyperref have to be called after babel, though.
1886 if (use_babel && !features.isRequired("jurabib")
1887 && !features.isRequired("hyperref")
1888 && !features.isRequired("vietnamese")
1889 && !features.isRequired("japanese")) {
1891 lyxpreamble += from_utf8(features.getBabelPresettings());
1892 lyxpreamble += from_utf8(babelCall(language_options.str(),
1893 features.needBabelLangOptions())) + '\n';
1894 lyxpreamble += from_utf8(features.getBabelPostsettings());
1897 // xunicode needs to be loaded at least after amsmath, amssymb,
1898 // esint and the other packages that provide special glyphs
1899 if (features.runparams().flavor == OutputParams::XETEX)
1900 lyxpreamble += "\\usepackage{xunicode}\n";
1902 // Polyglossia must be loaded last
1903 if (use_polyglossia) {
1905 lyxpreamble += "\\usepackage{polyglossia}\n";
1906 // set the main language
1907 lyxpreamble += "\\setdefaultlanguage";
1908 if (!language->polyglossiaOpts().empty())
1909 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1910 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1911 // now setup the other languages
1912 std::map<std::string, std::string> const polylangs =
1913 features.getPolyglossiaLanguages();
1914 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1915 mit != polylangs.end() ; ++mit) {
1916 lyxpreamble += "\\setotherlanguage";
1917 if (!mit->second.empty())
1918 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1919 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
1923 docstring const i18npreamble =
1924 features.getTClassI18nPreamble(use_babel, use_polyglossia);
1925 if (!i18npreamble.empty())
1926 lyxpreamble += i18npreamble + '\n';
1934 void BufferParams::useClassDefaults()
1936 DocumentClass const & tclass = documentClass();
1938 sides = tclass.sides();
1939 columns = tclass.columns();
1940 pagestyle = tclass.pagestyle();
1941 use_default_options = true;
1942 // Only if class has a ToC hierarchy
1943 if (tclass.hasTocLevels()) {
1944 secnumdepth = tclass.secnumdepth();
1945 tocdepth = tclass.tocdepth();
1950 bool BufferParams::hasClassDefaults() const
1952 DocumentClass const & tclass = documentClass();
1954 return sides == tclass.sides()
1955 && columns == tclass.columns()
1956 && pagestyle == tclass.pagestyle()
1957 && use_default_options
1958 && secnumdepth == tclass.secnumdepth()
1959 && tocdepth == tclass.tocdepth();
1963 DocumentClass const & BufferParams::documentClass() const
1969 DocumentClass const * BufferParams::documentClassPtr() const
1975 void BufferParams::setDocumentClass(DocumentClass const * const tc)
1977 // evil, but this function is evil
1978 doc_class_ = const_cast<DocumentClass *>(tc);
1982 bool BufferParams::setBaseClass(string const & classname)
1984 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1985 LayoutFileList & bcl = LayoutFileList::get();
1986 if (!bcl.haveClass(classname)) {
1988 bformat(_("The layout file:\n"
1990 "could not be found. A default textclass with default\n"
1991 "layouts will be used. LyX will not be able to produce\n"
1993 from_utf8(classname));
1994 frontend::Alert::error(_("Document class not found"), s);
1995 bcl.addEmptyClass(classname);
1998 bool const success = bcl[classname].load();
2001 bformat(_("Due to some error in it, the layout file:\n"
2003 "could not be loaded. A default textclass with default\n"
2004 "layouts will be used. LyX will not be able to produce\n"
2006 from_utf8(classname));
2007 frontend::Alert::error(_("Could not load class"), s);
2008 bcl.addEmptyClass(classname);
2011 pimpl_->baseClass_ = classname;
2012 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2017 LayoutFile const * BufferParams::baseClass() const
2019 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2020 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2026 LayoutFileIndex const & BufferParams::baseClassID() const
2028 return pimpl_->baseClass_;
2032 void BufferParams::makeDocumentClass()
2037 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layout_modules_));
2039 if (!local_layout.empty()) {
2040 TextClass::ReturnValues success =
2041 doc_class_->read(local_layout, TextClass::MODULE);
2042 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2043 docstring const msg = _("Error reading internal layout information");
2044 frontend::Alert::warning(_("Read Error"), msg);
2050 bool BufferParams::moduleCanBeAdded(string const & modName) const
2052 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2056 bool BufferParams::addLayoutModule(string const & modName)
2058 LayoutModuleList::const_iterator it = layout_modules_.begin();
2059 LayoutModuleList::const_iterator end = layout_modules_.end();
2060 for (; it != end; it++)
2063 layout_modules_.push_back(modName);
2068 string BufferParams::bufferFormat() const
2070 string format = documentClass().outputFormat();
2071 if (format == "latex") {
2074 if (encoding().package() == Encoding::japanese)
2081 bool BufferParams::isExportable(string const & format) const
2083 vector<string> backs = backends();
2084 for (vector<string>::const_iterator it = backs.begin();
2085 it != backs.end(); ++it)
2086 if (theConverters().isReachable(*it, format))
2092 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2094 vector<string> const backs = backends();
2095 set<string> excludes;
2096 if (useNonTeXFonts) {
2097 excludes.insert("latex");
2098 excludes.insert("pdflatex");
2100 vector<Format const *> result =
2101 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2102 for (vector<string>::const_iterator it = backs.begin() + 1;
2103 it != backs.end(); ++it) {
2104 vector<Format const *> r =
2105 theConverters().getReachable(*it, only_viewable, false, excludes);
2106 result.insert(result.end(), r.begin(), r.end());
2112 bool BufferParams::isExportableFormat(string const & format) const
2114 typedef vector<Format const *> Formats;
2116 formats = exportableFormats(true);
2117 Formats::const_iterator fit = formats.begin();
2118 Formats::const_iterator end = formats.end();
2119 for (; fit != end ; ++fit) {
2120 if ((*fit)->name() == format)
2127 vector<string> BufferParams::backends() const
2130 v.push_back(bufferFormat());
2131 // FIXME: Don't hardcode format names here, but use a flag
2132 if (v.back() == "latex") {
2133 v.push_back("pdflatex");
2134 v.push_back("luatex");
2135 v.push_back("dviluatex");
2136 v.push_back("xetex");
2137 } else if (v.back() == "xetex") {
2138 v.push_back("luatex");
2139 v.push_back("dviluatex");
2141 v.push_back("xhtml");
2142 v.push_back("text");
2148 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const format) const
2150 string const dformat = (format.empty() || format == "default") ?
2151 getDefaultOutputFormat() : format;
2152 DefaultFlavorCache::const_iterator it =
2153 default_flavors_.find(dformat);
2155 if (it != default_flavors_.end())
2158 OutputParams::FLAVOR result = OutputParams::LATEX;
2160 if (dformat == "xhtml")
2161 result = OutputParams::HTML;
2163 // Try to determine flavor of default output format
2164 vector<string> backs = backends();
2165 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2166 // Get shortest path to format
2167 Graph::EdgePath path;
2168 for (vector<string>::const_iterator it = backs.begin();
2169 it != backs.end(); ++it) {
2170 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2171 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2176 result = theConverters().getFlavor(path);
2179 // cache this flavor
2180 default_flavors_[dformat] = result;
2185 string BufferParams::getDefaultOutputFormat() const
2187 if (!default_output_format.empty()
2188 && default_output_format != "default")
2189 return default_output_format;
2192 || encoding().package() == Encoding::japanese) {
2193 vector<Format const *> const formats = exportableFormats(true);
2194 if (formats.empty())
2196 // return the first we find
2197 return formats.front()->name();
2199 return lyxrc.default_view_format;
2202 Font const BufferParams::getFont() const
2204 FontInfo f = documentClass().defaultfont();
2205 if (fonts_default_family == "rmdefault")
2206 f.setFamily(ROMAN_FAMILY);
2207 else if (fonts_default_family == "sfdefault")
2208 f.setFamily(SANS_FAMILY);
2209 else if (fonts_default_family == "ttdefault")
2210 f.setFamily(TYPEWRITER_FAMILY);
2211 return Font(f, language);
2215 bool BufferParams::isLatex() const
2217 return documentClass().outputType() == LATEX;
2221 bool BufferParams::isLiterate() const
2223 return documentClass().outputType() == LITERATE;
2227 bool BufferParams::isDocBook() const
2229 return documentClass().outputType() == DOCBOOK;
2233 void BufferParams::readPreamble(Lexer & lex)
2235 if (lex.getString() != "\\begin_preamble")
2236 lyxerr << "Error (BufferParams::readPreamble):"
2237 "consistency check failed." << endl;
2239 preamble = lex.getLongString("\\end_preamble");
2243 void BufferParams::readLocalLayout(Lexer & lex)
2245 if (lex.getString() != "\\begin_local_layout")
2246 lyxerr << "Error (BufferParams::readLocalLayout):"
2247 "consistency check failed." << endl;
2249 local_layout = lex.getLongString("\\end_local_layout");
2253 bool BufferParams::setLanguage(string const & lang)
2255 Language const *new_language = languages.getLanguage(lang);
2256 if (!new_language) {
2257 // Language lang was not found
2260 language = new_language;
2265 void BufferParams::readLanguage(Lexer & lex)
2267 if (!lex.next()) return;
2269 string const tmptok = lex.getString();
2271 // check if tmptok is part of tex_babel in tex-defs.h
2272 if (!setLanguage(tmptok)) {
2273 // Language tmptok was not found
2274 language = default_language;
2275 lyxerr << "Warning: Setting language `"
2276 << tmptok << "' to `" << language->lang()
2282 void BufferParams::readGraphicsDriver(Lexer & lex)
2287 string const tmptok = lex.getString();
2288 // check if tmptok is part of tex_graphics in tex_defs.h
2291 string const test = tex_graphics[n++];
2293 if (test == tmptok) {
2294 graphics_driver = tmptok;
2299 "Warning: graphics driver `$$Token' not recognized!\n"
2300 " Setting graphics driver to `default'.\n");
2301 graphics_driver = "default";
2308 void BufferParams::readBullets(Lexer & lex)
2313 int const index = lex.getInteger();
2315 int temp_int = lex.getInteger();
2316 user_defined_bullet(index).setFont(temp_int);
2317 temp_bullet(index).setFont(temp_int);
2319 user_defined_bullet(index).setCharacter(temp_int);
2320 temp_bullet(index).setCharacter(temp_int);
2322 user_defined_bullet(index).setSize(temp_int);
2323 temp_bullet(index).setSize(temp_int);
2327 void BufferParams::readBulletsLaTeX(Lexer & lex)
2329 // The bullet class should be able to read this.
2332 int const index = lex.getInteger();
2334 docstring const temp_str = lex.getDocString();
2336 user_defined_bullet(index).setText(temp_str);
2337 temp_bullet(index).setText(temp_str);
2341 void BufferParams::readModules(Lexer & lex)
2343 if (!lex.eatLine()) {
2344 lyxerr << "Error (BufferParams::readModules):"
2345 "Unexpected end of input." << endl;
2349 string mod = lex.getString();
2350 if (mod == "\\end_modules")
2352 addLayoutModule(mod);
2358 void BufferParams::readRemovedModules(Lexer & lex)
2360 if (!lex.eatLine()) {
2361 lyxerr << "Error (BufferParams::readRemovedModules):"
2362 "Unexpected end of input." << endl;
2366 string mod = lex.getString();
2367 if (mod == "\\end_removed_modules")
2369 removed_modules_.push_back(mod);
2372 // now we want to remove any removed modules that were previously
2373 // added. normally, that will be because default modules were added in
2374 // setBaseClass(), which gets called when \textclass is read at the
2375 // start of the read.
2376 list<string>::const_iterator rit = removed_modules_.begin();
2377 list<string>::const_iterator const ren = removed_modules_.end();
2378 for (; rit != ren; rit++) {
2379 LayoutModuleList::iterator const mit = layout_modules_.begin();
2380 LayoutModuleList::iterator const men = layout_modules_.end();
2381 LayoutModuleList::iterator found = find(mit, men, *rit);
2384 layout_modules_.erase(found);
2389 void BufferParams::readIncludeonly(Lexer & lex)
2391 if (!lex.eatLine()) {
2392 lyxerr << "Error (BufferParams::readIncludeonly):"
2393 "Unexpected end of input." << endl;
2397 string child = lex.getString();
2398 if (child == "\\end_includeonly")
2400 included_children_.push_back(child);
2406 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2408 char real_papersize = papersize;
2409 if (real_papersize == PAPER_DEFAULT)
2410 real_papersize = lyxrc.default_papersize;
2412 switch (real_papersize) {
2414 // could be anything, so don't guess
2416 case PAPER_CUSTOM: {
2417 if (purpose == XDVI && !paperwidth.empty() &&
2418 !paperheight.empty()) {
2419 // heightxwidth<unit>
2420 string first = paperwidth;
2421 string second = paperheight;
2422 if (orientation == ORIENTATION_LANDSCAPE)
2425 return first.erase(first.length() - 2)
2431 // dvips and dvipdfm do not know this
2432 if (purpose == DVIPS || purpose == DVIPDFM)
2436 if (purpose == DVIPS || purpose == DVIPDFM)
2440 if (purpose == DVIPS || 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 // dvipdfm does not know this
2471 if (purpose == DVIPDFM)
2475 if (purpose == DVIPDFM)
2479 if (purpose == DVIPS || purpose == DVIPDFM)
2483 if (purpose == DVIPS || purpose == DVIPDFM)
2487 if (purpose == DVIPS || purpose == DVIPDFM)
2491 if (purpose == DVIPS || purpose == DVIPDFM)
2495 if (purpose == DVIPS || purpose == DVIPDFM)
2499 if (purpose == DVIPS || purpose == DVIPDFM)
2503 if (purpose == DVIPS || purpose == DVIPDFM)
2507 if (purpose == DVIPS || purpose == DVIPDFM)
2511 if (purpose == DVIPS || purpose == DVIPDFM)
2515 if (purpose == DVIPS || purpose == DVIPDFM)
2519 if (purpose == DVIPS || purpose == DVIPDFM)
2523 if (purpose == DVIPS || purpose == DVIPDFM)
2527 if (purpose == DVIPS || purpose == DVIPDFM)
2531 if (purpose == DVIPS || purpose == DVIPDFM)
2535 if (purpose == DVIPS || purpose == DVIPDFM)
2538 case PAPER_USEXECUTIVE:
2539 // dvipdfm does not know this
2540 if (purpose == DVIPDFM)
2545 case PAPER_USLETTER:
2547 if (purpose == XDVI)
2554 string const BufferParams::dvips_options() const
2559 && papersize == PAPER_CUSTOM
2560 && !lyxrc.print_paper_dimension_flag.empty()
2561 && !paperwidth.empty()
2562 && !paperheight.empty()) {
2563 // using a custom papersize
2564 result = lyxrc.print_paper_dimension_flag;
2565 result += ' ' + paperwidth;
2566 result += ',' + paperheight;
2568 string const paper_option = paperSizeName(DVIPS);
2569 if (!paper_option.empty() && (paper_option != "letter" ||
2570 orientation != ORIENTATION_LANDSCAPE)) {
2571 // dvips won't accept -t letter -t landscape.
2572 // In all other cases, include the paper size
2574 result = lyxrc.print_paper_flag;
2575 result += ' ' + paper_option;
2578 if (orientation == ORIENTATION_LANDSCAPE &&
2579 papersize != PAPER_CUSTOM)
2580 result += ' ' + lyxrc.print_landscape_flag;
2585 string const BufferParams::font_encoding() const
2587 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2591 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2593 if (lang_package != "auto" && lang_package != "babel"
2594 && lang_package != "default" && lang_package != "none")
2595 return lang_package;
2596 if (lyxrc.language_package_selection == LyXRC::LP_CUSTOM)
2597 return lyxrc.language_custom_package;
2598 // suppress the babel call if there is no BabelName defined
2599 // for the document language in the lib/languages file and if no
2600 // other languages are used (lang_opts is then empty)
2601 if (lang_opts.empty())
2603 // either a specific language (AsBabelOptions setting in
2604 // lib/languages) or the prefs require the languages to
2605 // be submitted to babel itself (not the class).
2607 return "\\usepackage[" + lang_opts + "]{babel}";
2608 return "\\usepackage{babel}";
2612 docstring BufferParams::getGraphicsDriver(string const & package) const
2616 if (package == "geometry") {
2617 if (graphics_driver == "dvips"
2618 || graphics_driver == "dvipdfm"
2619 || graphics_driver == "pdftex"
2620 || graphics_driver == "vtex")
2621 result = from_ascii(graphics_driver);
2622 else if (graphics_driver == "dvipdfmx")
2623 result = from_ascii("dvipdfm");
2630 void BufferParams::writeEncodingPreamble(otexstream & os,
2631 LaTeXFeatures & features) const
2633 // XeTeX does not need this
2634 if (features.runparams().flavor == OutputParams::XETEX)
2636 // LuaTeX neither, but with tex fonts, we need to load
2637 // the luainputenc package.
2638 if (features.runparams().flavor == OutputParams::LUATEX
2639 || features.runparams().flavor == OutputParams::DVILUATEX) {
2640 if (!useNonTeXFonts && inputenc != "default"
2641 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2642 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2643 os << "\\usepackage[utf8]{luainputenc}\n";
2647 if (inputenc == "auto") {
2648 string const doc_encoding =
2649 language->encoding()->latexName();
2650 Encoding::Package const package =
2651 language->encoding()->package();
2653 // Create a list with all the input encodings used
2655 set<string> encodings =
2656 features.getEncodingSet(doc_encoding);
2658 // If the "japanese" package (i.e. pLaTeX) is used,
2659 // inputenc must be omitted.
2660 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2661 if (package == Encoding::japanese)
2662 features.require("japanese");
2664 if ((!encodings.empty() || package == Encoding::inputenc)
2665 && !features.isRequired("japanese")) {
2666 os << "\\usepackage[";
2667 set<string>::const_iterator it = encodings.begin();
2668 set<string>::const_iterator const end = encodings.end();
2670 os << from_ascii(*it);
2673 for (; it != end; ++it)
2674 os << ',' << from_ascii(*it);
2675 if (package == Encoding::inputenc) {
2676 if (!encodings.empty())
2678 os << from_ascii(doc_encoding);
2680 os << "]{inputenc}\n";
2682 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2683 if (language->encoding()->name() == "utf8-cjk"
2684 && LaTeXFeatures::isAvailable("CJKutf8"))
2685 os << "\\usepackage{CJKutf8}\n";
2687 os << "\\usepackage{CJK}\n";
2689 } else if (inputenc != "default") {
2690 switch (encoding().package()) {
2691 case Encoding::none:
2692 case Encoding::japanese:
2694 case Encoding::inputenc:
2695 // do not load inputenc if japanese is used
2696 if (features.isRequired("japanese"))
2698 os << "\\usepackage[" << from_ascii(inputenc)
2702 if (encoding().name() == "utf8-cjk"
2703 && LaTeXFeatures::isAvailable("CJKutf8"))
2704 os << "\\usepackage{CJKutf8}\n";
2706 os << "\\usepackage{CJK}\n";
2711 // The encoding "armscii8" (for Armenian) is only available when
2712 // the package "armtex" is loaded.
2713 if (language->encoding()->latexName() == "armscii8"
2714 || inputenc == "armscii8")
2715 os << "\\usepackage{armtex}\n";
2719 string const BufferParams::parseFontName(string const & name) const
2721 string mangled = name;
2722 size_t const idx = mangled.find('[');
2723 if (idx == string::npos || idx == 0)
2726 return mangled.substr(0, idx - 1);
2730 string const BufferParams::loadFonts(string const & rm,
2731 string const & sf, string const & tt,
2732 bool const & sc, bool const & osf,
2733 int const & sfscale, int const & ttscale,
2734 bool const & use_systemfonts,
2735 LaTeXFeatures & features) const
2737 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2738 several packages have been replaced by others, that might not
2739 be installed on every system. We have to take care for that
2740 (see psnfss.pdf). We try to support all psnfss fonts as well
2741 as the fonts that have become de facto standard in the LaTeX
2742 world (e.g. Latin Modern). We do not support obsolete fonts
2743 (like PSLatex). In general, it should be possible to mix any
2744 rm font with any sf or tt font, respectively. (JSpitzm)
2746 -- separate math fonts.
2749 if (rm == "default" && sf == "default" && tt == "default")
2755 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2756 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2757 * Mapping=tex-text option assures TeX ligatures (such as "--")
2758 * are resolved. Note that tt does not use these ligatures.
2760 * -- add more GUI options?
2761 * -- add more fonts (fonts for other scripts)
2762 * -- if there's a way to find out if a font really supports
2763 * OldStyle, enable/disable the widget accordingly.
2765 if (use_systemfonts && features.isAvailable("fontspec")) {
2766 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2767 // However, until v.2 (2010/07/11) fontspec only knew
2768 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2769 // was introduced for both XeTeX and LuaTeX (LuaTeX
2770 // didn't understand "Mapping=tex-text", while XeTeX
2771 // understood both. With most recent versions, both
2772 // variants are understood by both engines. However,
2773 // we want to provide support for at least TeXLive 2009
2774 // (for XeTeX; LuaTeX is only supported as of v.2)
2775 string const texmapping =
2776 (features.runparams().flavor == OutputParams::XETEX) ?
2777 "Mapping=tex-text" : "Ligatures=TeX";
2778 if (rm != "default") {
2779 os << "\\setmainfont[" << texmapping;
2781 os << ",Numbers=OldStyle";
2782 os << "]{" << parseFontName(rm) << "}\n";
2784 if (sf != "default") {
2785 string const sans = parseFontName(sf);
2787 os << "\\setsansfont[Scale="
2788 << float(sfscale) / 100
2789 << "," << texmapping << "]{"
2792 os << "\\setsansfont[" << texmapping << "]{"
2795 if (tt != "default") {
2796 string const mono = parseFontName(tt);
2798 os << "\\setmonofont[Scale="
2799 << float(ttscale) / 100
2803 os << "\\setmonofont{"
2810 // Computer Modern (must be explicitly selectable -- there might be classes
2811 // that define a different default font!
2813 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2814 // osf for Computer Modern needs eco.sty
2816 os << "\\usepackage{eco}\n";
2818 // Latin Modern Roman
2819 else if (rm == "lmodern")
2820 os << "\\usepackage{lmodern}\n";
2822 else if (rm == "ae") {
2823 // not needed when using OT1 font encoding.
2824 if (font_encoding() != "default")
2825 os << "\\usepackage{ae,aecompl}\n";
2828 else if (rm == "times") {
2829 // try to load the best available package
2830 if (LaTeXFeatures::isAvailable("mathptmx"))
2831 os << "\\usepackage{mathptmx}\n";
2832 else if (LaTeXFeatures::isAvailable("mathptm"))
2833 os << "\\usepackage{mathptm}\n";
2835 os << "\\usepackage{times}\n";
2838 else if (rm == "palatino") {
2839 // try to load the best available package
2840 if (LaTeXFeatures::isAvailable("mathpazo")) {
2841 os << "\\usepackage";
2847 // "osf" includes "sc"!
2851 os << "{mathpazo}\n";
2853 else if (LaTeXFeatures::isAvailable("mathpple"))
2854 os << "\\usepackage{mathpple}\n";
2856 os << "\\usepackage{palatino}\n";
2859 else if (rm == "utopia") {
2860 // fourier supersedes utopia.sty, but does
2861 // not work with OT1 encoding.
2862 if (LaTeXFeatures::isAvailable("fourier")
2863 && font_encoding() != "default") {
2864 os << "\\usepackage";
2875 os << "{fourier}\n";
2878 os << "\\usepackage{utopia}\n";
2880 // Bera (complete fontset)
2881 else if (rm == "bera" && sf == "default" && tt == "default")
2882 os << "\\usepackage{bera}\n";
2884 else if (rm != "default")
2885 os << "\\usepackage" << "{" << rm << "}\n";
2888 // Helvetica, Bera Sans
2889 if (sf == "helvet" || sf == "berasans") {
2891 os << "\\usepackage[scaled=" << float(sfscale) / 100
2892 << "]{" << sf << "}\n";
2894 os << "\\usepackage{" << sf << "}\n";
2897 else if (sf == "avant")
2898 os << "\\usepackage{" << sf << "}\n";
2899 // Computer Modern, Latin Modern, CM Bright
2900 else if (sf != "default")
2901 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2903 // monospaced/typewriter
2904 // Courier, LuxiMono
2905 if (tt == "luximono" || tt == "beramono") {
2907 os << "\\usepackage[scaled=" << float(ttscale) / 100
2908 << "]{" << tt << "}\n";
2910 os << "\\usepackage{" << tt << "}\n";
2913 else if (tt == "courier" )
2914 os << "\\usepackage{" << tt << "}\n";
2915 // Computer Modern, Latin Modern, CM Bright
2916 else if (tt != "default")
2917 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2923 Encoding const & BufferParams::encoding() const
2925 // FIXME: actually, we should check for the flavor
2926 // or runparams.isFullyUnicode() here:
2927 // This check will not work with XeTeX/LuaTeX and tex fonts.
2928 // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2930 return *(encodings.fromLaTeXName("utf8-plain"));
2931 if (inputenc == "auto" || inputenc == "default")
2932 return *language->encoding();
2933 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2936 LYXERR0("Unknown inputenc value `" << inputenc
2937 << "'. Using `auto' instead.");
2938 return *language->encoding();
2942 CiteEngine BufferParams::citeEngine() const
2944 // FIXME the class should provide the numerical/
2945 // authoryear choice
2946 if (documentClass().provides("natbib")
2947 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2948 return ENGINE_NATBIB_AUTHORYEAR;
2949 return cite_engine_;
2953 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2955 cite_engine_ = cite_engine;