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("mhchem");
454 packages.push_back("undertilde");
460 AuthorList & BufferParams::authors()
462 return pimpl_->authorlist;
466 AuthorList const & BufferParams::authors() const
468 return pimpl_->authorlist;
472 BranchList & BufferParams::branchlist()
474 return pimpl_->branchlist;
478 BranchList const & BufferParams::branchlist() const
480 return pimpl_->branchlist;
484 IndicesList & BufferParams::indiceslist()
486 return pimpl_->indiceslist;
490 IndicesList const & BufferParams::indiceslist() const
492 return pimpl_->indiceslist;
496 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
498 LASSERT(index < 4, /**/);
499 return pimpl_->temp_bullets[index];
503 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
505 LASSERT(index < 4, /**/);
506 return pimpl_->temp_bullets[index];
510 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
512 LASSERT(index < 4, /**/);
513 return pimpl_->user_defined_bullets[index];
517 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
519 LASSERT(index < 4, /**/);
520 return pimpl_->user_defined_bullets[index];
524 Spacing & BufferParams::spacing()
526 return pimpl_->spacing;
530 Spacing const & BufferParams::spacing() const
532 return pimpl_->spacing;
536 PDFOptions & BufferParams::pdfoptions()
538 return pimpl_->pdfoptions;
542 PDFOptions const & BufferParams::pdfoptions() const
544 return pimpl_->pdfoptions;
548 HSpace const & BufferParams::getIndentation() const
550 return pimpl_->indentation;
554 void BufferParams::setIndentation(HSpace const & indent)
556 pimpl_->indentation = indent;
560 VSpace const & BufferParams::getDefSkip() const
562 return pimpl_->defskip;
566 void BufferParams::setDefSkip(VSpace const & vs)
568 // DEFSKIP will cause an infinite loop
569 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
570 pimpl_->defskip = vs;
574 string BufferParams::readToken(Lexer & lex, string const & token,
575 FileName const & filepath)
577 if (token == "\\textclass") {
579 string const classname = lex.getString();
580 // if there exists a local layout file, ignore the system one
581 // NOTE: in this case, the textclass (.cls file) is assumed to
584 LayoutFileList & bcl = LayoutFileList::get();
585 if (tcp.empty() && !filepath.empty())
586 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
590 setBaseClass(classname);
591 // We assume that a tex class exists for local or unknown
592 // layouts so this warning, will only be given for system layouts.
593 if (!baseClass()->isTeXClassAvailable()) {
594 docstring const desc =
595 translateIfPossible(from_utf8(baseClass()->description()));
596 docstring const prereqs =
597 from_utf8(baseClass()->prerequisites());
598 docstring const msg =
599 bformat(_("The selected document class\n"
601 "requires external files that are not available.\n"
602 "The document class can still be used, but the\n"
603 "document cannot be compiled until the following\n"
604 "prerequisites are installed:\n"
606 "See section 3.1.2.2 (Class Availability) of the\n"
607 "User's Guide for more information."), desc, prereqs);
608 frontend::Alert::warning(_("Document class not available"),
611 } else if (token == "\\begin_preamble") {
613 } else if (token == "\\begin_local_layout") {
614 readLocalLayout(lex);
615 } else if (token == "\\begin_modules") {
617 } else if (token == "\\begin_removed_modules") {
618 readRemovedModules(lex);
619 } else if (token == "\\begin_includeonly") {
620 readIncludeonly(lex);
621 } else if (token == "\\maintain_unincluded_children") {
622 lex >> maintain_unincluded_children;
623 } else if (token == "\\options") {
625 options = lex.getString();
626 } else if (token == "\\use_default_options") {
627 lex >> use_default_options;
628 } else if (token == "\\master") {
630 master = lex.getString();
631 } else if (token == "\\suppress_date") {
632 lex >> suppress_date;
633 } else if (token == "\\justification") {
634 lex >> justification;
635 } else if (token == "\\language") {
637 } else if (token == "\\language_package") {
639 lang_package = lex.getString();
640 } else if (token == "\\inputencoding") {
642 } else if (token == "\\graphics") {
643 readGraphicsDriver(lex);
644 } else if (token == "\\default_output_format") {
645 lex >> default_output_format;
646 } else if (token == "\\bibtex_command") {
648 bibtex_command = lex.getString();
649 } else if (token == "\\index_command") {
651 index_command = lex.getString();
652 } else if (token == "\\fontencoding") {
654 fontenc = lex.getString();
655 } else if (token == "\\font_roman") {
657 fonts_roman = lex.getString();
658 } else if (token == "\\font_sans") {
660 fonts_sans = lex.getString();
661 } else if (token == "\\font_typewriter") {
663 fonts_typewriter = lex.getString();
664 } else if (token == "\\font_default_family") {
665 lex >> fonts_default_family;
666 } else if (token == "\\use_non_tex_fonts") {
667 lex >> useNonTeXFonts;
668 } else if (token == "\\font_sc") {
669 lex >> fonts_expert_sc;
670 } else if (token == "\\font_osf") {
671 lex >> fonts_old_figures;
672 } else if (token == "\\font_sf_scale") {
673 lex >> fonts_sans_scale;
674 } else if (token == "\\font_tt_scale") {
675 lex >> fonts_typewriter_scale;
676 } else if (token == "\\font_cjk") {
678 } else if (token == "\\paragraph_separation") {
681 paragraph_separation = parseptranslator().find(parsep);
682 } else if (token == "\\paragraph_indentation") {
684 string indentation = lex.getString();
685 pimpl_->indentation = HSpace(indentation);
686 } else if (token == "\\defskip") {
688 string const defskip = lex.getString();
689 pimpl_->defskip = VSpace(defskip);
690 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
692 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
693 } else if (token == "\\quotes_language") {
696 quotes_language = quoteslangtranslator().find(quotes_lang);
697 } else if (token == "\\papersize") {
700 papersize = papersizetranslator().find(ppsize);
701 } else if (token == "\\use_geometry") {
703 } else if (token == "\\use_package") {
708 use_package(package, packagetranslator().find(use));
709 } else if (token == "\\cite_engine") {
712 cite_engine_ = citeenginetranslator().find(engine);
713 } else if (token == "\\biblio_style") {
715 biblio_style = lex.getString();
716 } else if (token == "\\use_bibtopic") {
718 } else if (token == "\\use_indices") {
720 } else if (token == "\\tracking_changes") {
722 } else if (token == "\\output_changes") {
723 lex >> outputChanges;
724 } else if (token == "\\branch") {
726 docstring branch = lex.getDocString();
727 branchlist().add(branch);
730 string const tok = lex.getString();
731 if (tok == "\\end_branch")
733 Branch * branch_ptr = branchlist().find(branch);
734 if (tok == "\\selected") {
737 branch_ptr->setSelected(lex.getInteger());
739 if (tok == "\\filename_suffix") {
742 branch_ptr->setFileNameSuffix(lex.getInteger());
744 if (tok == "\\color") {
746 string color = lex.getString();
748 branch_ptr->setColor(color);
749 // Update also the Color table:
751 color = lcolor.getX11Name(Color_background);
753 lcolor.setColor(to_utf8(branch), color);
756 } else if (token == "\\index") {
758 docstring index = lex.getDocString();
760 indiceslist().add(index);
763 string const tok = lex.getString();
764 if (tok == "\\end_index")
766 Index * index_ptr = indiceslist().find(index);
767 if (tok == "\\shortcut") {
769 shortcut = lex.getDocString();
771 index_ptr->setShortcut(shortcut);
773 if (tok == "\\color") {
775 string color = lex.getString();
777 index_ptr->setColor(color);
778 // Update also the Color table:
780 color = lcolor.getX11Name(Color_background);
782 if (!shortcut.empty())
783 lcolor.setColor(to_utf8(shortcut), color);
786 } else if (token == "\\author") {
788 istringstream ss(lex.getString());
791 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
792 } else if (token == "\\paperorientation") {
795 orientation = paperorientationtranslator().find(orient);
796 } else if (token == "\\backgroundcolor") {
798 backgroundcolor = lyx::rgbFromHexName(lex.getString());
799 isbackgroundcolor = true;
800 } else if (token == "\\fontcolor") {
802 fontcolor = lyx::rgbFromHexName(lex.getString());
804 } else if (token == "\\notefontcolor") {
806 string color = lex.getString();
807 notefontcolor = lyx::rgbFromHexName(color);
808 } else if (token == "\\boxbgcolor") {
810 string color = lex.getString();
811 boxbgcolor = lyx::rgbFromHexName(color);
812 } else if (token == "\\paperwidth") {
814 } else if (token == "\\paperheight") {
816 } else if (token == "\\leftmargin") {
818 } else if (token == "\\topmargin") {
820 } else if (token == "\\rightmargin") {
822 } else if (token == "\\bottommargin") {
824 } else if (token == "\\headheight") {
826 } else if (token == "\\headsep") {
828 } else if (token == "\\footskip") {
830 } else if (token == "\\columnsep") {
832 } else if (token == "\\paperfontsize") {
834 } else if (token == "\\papercolumns") {
836 } else if (token == "\\listings_params") {
839 listings_params = InsetListingsParams(par).params();
840 } else if (token == "\\papersides") {
843 sides = sidestranslator().find(psides);
844 } else if (token == "\\paperpagestyle") {
846 } else if (token == "\\bullet") {
848 } else if (token == "\\bulletLaTeX") {
849 readBulletsLaTeX(lex);
850 } else if (token == "\\secnumdepth") {
852 } else if (token == "\\tocdepth") {
854 } else if (token == "\\spacing") {
858 if (nspacing == "other") {
861 spacing().set(spacetranslator().find(nspacing), tmp_val);
862 } else if (token == "\\float_placement") {
863 lex >> float_placement;
865 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
866 string toktmp = pdfoptions().readToken(lex, token);
867 if (!toktmp.empty()) {
868 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
872 } else if (token == "\\html_math_output") {
875 html_math_output = static_cast<MathOutput>(temp);
876 } else if (token == "\\html_be_strict") {
877 lex >> html_be_strict;
878 } else if (token == "\\html_css_as_file") {
879 lex >> html_css_as_file;
880 } else if (token == "\\html_math_img_scale") {
881 lex >> html_math_img_scale;
882 } else if (token == "\\html_latex_start") {
884 html_latex_start = lex.getString();
885 } else if (token == "\\html_latex_end") {
887 html_latex_end = lex.getString();
888 } else if (token == "\\output_sync") {
890 } else if (token == "\\output_sync_macro") {
891 lex >> output_sync_macro;
892 } else if (token == "\\use_refstyle") {
895 lyxerr << "BufferParams::readToken(): Unknown token: " <<
904 void BufferParams::writeFile(ostream & os) const
906 // The top of the file is written by the buffer.
907 // Prints out the buffer info into the .lyx file given by file
910 os << "\\textclass " << baseClass()->name() << '\n';
913 if (!preamble.empty()) {
914 // remove '\n' from the end of preamble
915 string const tmppreamble = rtrim(preamble, "\n");
916 os << "\\begin_preamble\n"
918 << "\n\\end_preamble\n";
922 if (!options.empty()) {
923 os << "\\options " << options << '\n';
926 // use the class options defined in the layout?
927 os << "\\use_default_options "
928 << convert<string>(use_default_options) << "\n";
930 // the master document
931 if (!master.empty()) {
932 os << "\\master " << master << '\n';
936 if (!removed_modules_.empty()) {
937 os << "\\begin_removed_modules" << '\n';
938 list<string>::const_iterator it = removed_modules_.begin();
939 list<string>::const_iterator en = removed_modules_.end();
940 for (; it != en; it++)
942 os << "\\end_removed_modules" << '\n';
946 if (!layout_modules_.empty()) {
947 os << "\\begin_modules" << '\n';
948 LayoutModuleList::const_iterator it = layout_modules_.begin();
949 LayoutModuleList::const_iterator en = layout_modules_.end();
950 for (; it != en; it++)
952 os << "\\end_modules" << '\n';
956 if (!included_children_.empty()) {
957 os << "\\begin_includeonly" << '\n';
958 list<string>::const_iterator it = included_children_.begin();
959 list<string>::const_iterator en = included_children_.end();
960 for (; it != en; it++)
962 os << "\\end_includeonly" << '\n';
964 os << "\\maintain_unincluded_children "
965 << convert<string>(maintain_unincluded_children) << '\n';
967 // local layout information
968 if (!local_layout.empty()) {
969 // remove '\n' from the end
970 string const tmplocal = rtrim(local_layout, "\n");
971 os << "\\begin_local_layout\n"
973 << "\n\\end_local_layout\n";
976 // then the text parameters
977 if (language != ignore_language)
978 os << "\\language " << language->lang() << '\n';
979 os << "\\language_package " << lang_package
980 << "\n\\inputencoding " << inputenc
981 << "\n\\fontencoding " << fontenc
982 << "\n\\font_roman " << fonts_roman
983 << "\n\\font_sans " << fonts_sans
984 << "\n\\font_typewriter " << fonts_typewriter
985 << "\n\\font_default_family " << fonts_default_family
986 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
987 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
988 << "\n\\font_osf " << convert<string>(fonts_old_figures)
989 << "\n\\font_sf_scale " << fonts_sans_scale
990 << "\n\\font_tt_scale " << fonts_typewriter_scale
992 if (!fonts_cjk.empty()) {
993 os << "\\font_cjk " << fonts_cjk << '\n';
995 os << "\n\\graphics " << graphics_driver << '\n';
996 os << "\\default_output_format " << default_output_format << '\n';
997 os << "\\output_sync " << output_sync << '\n';
998 if (!output_sync_macro.empty())
999 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1000 os << "\\bibtex_command " << bibtex_command << '\n';
1001 os << "\\index_command " << index_command << '\n';
1003 if (!float_placement.empty()) {
1004 os << "\\float_placement " << float_placement << '\n';
1006 os << "\\paperfontsize " << fontsize << '\n';
1008 spacing().writeFile(os);
1009 pdfoptions().writeFile(os);
1011 os << "\\papersize " << string_papersize[papersize]
1012 << "\n\\use_geometry " << convert<string>(use_geometry);
1013 vector<string> const & packages = auto_packages();
1014 for (size_t i = 0; i < packages.size(); ++i)
1015 os << "\n\\use_package " << packages[i] << ' '
1016 << use_package(packages[i]);
1017 os << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
1018 << "\n\\biblio_style " << biblio_style
1019 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1020 << "\n\\use_indices " << convert<string>(use_indices)
1021 << "\n\\paperorientation " << string_orientation[orientation]
1022 << "\n\\suppress_date " << convert<string>(suppress_date)
1023 << "\n\\justification " << convert<string>(justification)
1024 << "\n\\use_refstyle " << use_refstyle
1026 if (isbackgroundcolor == true)
1027 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1028 if (isfontcolor == true)
1029 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1030 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1031 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1032 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1033 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1035 BranchList::const_iterator it = branchlist().begin();
1036 BranchList::const_iterator end = branchlist().end();
1037 for (; it != end; ++it) {
1038 os << "\\branch " << to_utf8(it->branch())
1039 << "\n\\selected " << it->isSelected()
1040 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1041 << "\n\\color " << lyx::X11hexname(it->color())
1046 IndicesList::const_iterator iit = indiceslist().begin();
1047 IndicesList::const_iterator iend = indiceslist().end();
1048 for (; iit != iend; ++iit) {
1049 os << "\\index " << to_utf8(iit->index())
1050 << "\n\\shortcut " << to_utf8(iit->shortcut())
1051 << "\n\\color " << lyx::X11hexname(iit->color())
1056 if (!paperwidth.empty())
1057 os << "\\paperwidth "
1058 << VSpace(paperwidth).asLyXCommand() << '\n';
1059 if (!paperheight.empty())
1060 os << "\\paperheight "
1061 << VSpace(paperheight).asLyXCommand() << '\n';
1062 if (!leftmargin.empty())
1063 os << "\\leftmargin "
1064 << VSpace(leftmargin).asLyXCommand() << '\n';
1065 if (!topmargin.empty())
1066 os << "\\topmargin "
1067 << VSpace(topmargin).asLyXCommand() << '\n';
1068 if (!rightmargin.empty())
1069 os << "\\rightmargin "
1070 << VSpace(rightmargin).asLyXCommand() << '\n';
1071 if (!bottommargin.empty())
1072 os << "\\bottommargin "
1073 << VSpace(bottommargin).asLyXCommand() << '\n';
1074 if (!headheight.empty())
1075 os << "\\headheight "
1076 << VSpace(headheight).asLyXCommand() << '\n';
1077 if (!headsep.empty())
1079 << VSpace(headsep).asLyXCommand() << '\n';
1080 if (!footskip.empty())
1082 << VSpace(footskip).asLyXCommand() << '\n';
1083 if (!columnsep.empty())
1084 os << "\\columnsep "
1085 << VSpace(columnsep).asLyXCommand() << '\n';
1086 os << "\\secnumdepth " << secnumdepth
1087 << "\n\\tocdepth " << tocdepth
1088 << "\n\\paragraph_separation "
1089 << string_paragraph_separation[paragraph_separation];
1090 if (!paragraph_separation)
1091 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1093 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1094 os << "\n\\quotes_language "
1095 << string_quotes_language[quotes_language]
1096 << "\n\\papercolumns " << columns
1097 << "\n\\papersides " << sides
1098 << "\n\\paperpagestyle " << pagestyle << '\n';
1099 if (!listings_params.empty())
1100 os << "\\listings_params \"" <<
1101 InsetListingsParams(listings_params).encodedString() << "\"\n";
1102 for (int i = 0; i < 4; ++i) {
1103 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1104 if (user_defined_bullet(i).getFont() != -1) {
1105 os << "\\bullet " << i << " "
1106 << user_defined_bullet(i).getFont() << " "
1107 << user_defined_bullet(i).getCharacter() << " "
1108 << user_defined_bullet(i).getSize() << "\n";
1112 os << "\\bulletLaTeX " << i << " \""
1113 << lyx::to_ascii(user_defined_bullet(i).getText())
1119 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1120 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1121 << "\\html_math_output " << html_math_output << '\n'
1122 << "\\html_css_as_file " << html_css_as_file << '\n'
1123 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1125 if (html_math_img_scale != 1.0)
1126 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1127 if (!html_latex_start.empty())
1128 os << "\\html_latex_start " << html_latex_start << '\n';
1129 if (!html_latex_end.empty())
1130 os << "\\html_latex_end " << html_latex_end << '\n';
1132 os << pimpl_->authorlist;
1136 void BufferParams::validate(LaTeXFeatures & features) const
1138 features.require(documentClass().requires());
1140 if (outputChanges) {
1141 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1142 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1143 LaTeXFeatures::isAvailable("xcolor");
1145 switch (features.runparams().flavor) {
1146 case OutputParams::LATEX:
1147 case OutputParams::DVILUATEX:
1149 features.require("ct-dvipost");
1150 features.require("dvipost");
1151 } else if (xcolorulem) {
1152 features.require("ct-xcolor-ulem");
1153 features.require("ulem");
1154 features.require("xcolor");
1156 features.require("ct-none");
1159 case OutputParams::LUATEX:
1160 case OutputParams::PDFLATEX:
1161 case OutputParams::XETEX:
1163 features.require("ct-xcolor-ulem");
1164 features.require("ulem");
1165 features.require("xcolor");
1166 // improves color handling in PDF output
1167 features.require("pdfcolmk");
1169 features.require("ct-none");
1177 // Floats with 'Here definitely' as default setting.
1178 if (float_placement.find('H') != string::npos)
1179 features.require("float");
1181 for (PackageMap::const_iterator it = use_packages.begin();
1182 it != use_packages.end(); ++it) {
1183 if (it->first == "amsmath") {
1184 // AMS Style is at document level
1185 if (it->second == package_on ||
1186 documentClass().provides("amsmath"))
1187 features.require(it->first);
1188 } else if (it->second == package_on)
1189 features.require(it->first);
1192 // Document-level line spacing
1193 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1194 features.require("setspace");
1196 // the bullet shapes are buffer level not paragraph level
1197 // so they are tested here
1198 for (int i = 0; i < 4; ++i) {
1199 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1201 int const font = user_defined_bullet(i).getFont();
1203 int const c = user_defined_bullet(i).getCharacter();
1209 features.require("latexsym");
1211 } else if (font == 1) {
1212 features.require("amssymb");
1213 } else if (font >= 2 && font <= 5) {
1214 features.require("pifont");
1218 if (pdfoptions().use_hyperref) {
1219 features.require("hyperref");
1220 // due to interferences with babel and hyperref, the color package has to
1221 // be loaded after hyperref when hyperref is used with the colorlinks
1222 // option, see http://www.lyx.org/trac/ticket/5291
1223 if (pdfoptions().colorlinks)
1224 features.require("color");
1227 if (features.runparams().flavor == OutputParams::XETEX
1229 features.require("polyglossia");
1231 if (language->lang() == "vietnamese")
1232 features.require("vietnamese");
1233 else if (language->lang() == "japanese")
1234 features.require("japanese");
1238 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1239 FileName const & filepath) const
1241 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1242 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1243 // \RequirePackage to do so, rather than the normal \usepackage
1244 // Do not try to load any other package before the document class, unless you
1245 // have a thorough understanding of the LATEX internals and know exactly what you
1247 if (features.mustProvide("fix-cm"))
1248 os << "\\RequirePackage{fix-cm}\n";
1250 os << "\\documentclass";
1252 DocumentClass const & tclass = documentClass();
1254 ostringstream clsoptions; // the document class options.
1256 if (tokenPos(tclass.opt_fontsize(),
1257 '|', fontsize) >= 0) {
1258 // only write if existing in list (and not default)
1259 clsoptions << fontsize << "pt,";
1262 // all paper sizes except of A4, A5, B5 and the US sizes need the
1264 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1265 && papersize != PAPER_USLETTER
1266 && papersize != PAPER_USLEGAL
1267 && papersize != PAPER_USEXECUTIVE
1268 && papersize != PAPER_A4
1269 && papersize != PAPER_A5
1270 && papersize != PAPER_B5;
1272 if (!use_geometry) {
1273 switch (papersize) {
1275 clsoptions << "a4paper,";
1277 case PAPER_USLETTER:
1278 clsoptions << "letterpaper,";
1281 clsoptions << "a5paper,";
1284 clsoptions << "b5paper,";
1286 case PAPER_USEXECUTIVE:
1287 clsoptions << "executivepaper,";
1290 clsoptions << "legalpaper,";
1324 if (sides != tclass.sides()) {
1327 clsoptions << "oneside,";
1330 clsoptions << "twoside,";
1336 if (columns != tclass.columns()) {
1338 clsoptions << "twocolumn,";
1340 clsoptions << "onecolumn,";
1344 && orientation == ORIENTATION_LANDSCAPE)
1345 clsoptions << "landscape,";
1347 // language should be a parameter to \documentclass
1348 if (language->babel() == "hebrew"
1349 && default_language->babel() != "hebrew")
1350 // This seems necessary
1351 features.useLanguage(default_language);
1353 ostringstream language_options;
1354 bool const use_babel = features.useBabel() && !tclass.provides("babel");
1355 bool const use_polyglossia = features.usePolyglossia();
1356 bool const global = lyxrc.language_global_options;
1357 if (use_babel || (use_polyglossia && global)) {
1358 language_options << features.getLanguages();
1359 if (!language->babel().empty()) {
1360 if (!language_options.str().empty())
1361 language_options << ',';
1362 language_options << language->babel();
1364 if (global && !features.needBabelLangOptions())
1365 clsoptions << language_options.str() << ',';
1368 // the predefined options from the layout
1369 if (use_default_options && !tclass.options().empty())
1370 clsoptions << tclass.options() << ',';
1372 // the user-defined options
1373 if (!options.empty()) {
1374 clsoptions << options << ',';
1377 string strOptions(clsoptions.str());
1378 if (!strOptions.empty()) {
1379 strOptions = rtrim(strOptions, ",");
1381 os << '[' << from_utf8(strOptions) << ']';
1384 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1385 // end of \documentclass defs
1387 // if we use fontspec, we have to load the AMS packages here
1388 string const ams = features.loadAMSPackages();
1389 if (useNonTeXFonts && !ams.empty())
1390 os << from_ascii(ams);
1393 os << "\\usepackage{fontspec}\n";
1395 // font selection must be done before loading fontenc.sty
1396 string const fonts =
1397 loadFonts(fonts_roman, fonts_sans, fonts_typewriter,
1398 fonts_expert_sc, fonts_old_figures,
1399 fonts_sans_scale, fonts_typewriter_scale,
1400 useNonTeXFonts, features);
1402 os << from_utf8(fonts);
1404 if (fonts_default_family != "default")
1405 os << "\\renewcommand{\\familydefault}{\\"
1406 << from_ascii(fonts_default_family) << "}\n";
1408 // set font encoding
1409 // for arabic_arabi and farsi we also need to load the LAE and
1411 // XeTeX and LuaTeX (with OS fonts) work without fontenc
1412 if (font_encoding() != "default" && language->lang() != "japanese"
1413 && !useNonTeXFonts && !tclass.provides("fontenc")) {
1414 size_t fars = language_options.str().find("farsi");
1415 size_t arab = language_options.str().find("arabic");
1416 if (language->lang() == "arabic_arabi"
1417 || language->lang() == "farsi" || fars != string::npos
1418 || arab != string::npos) {
1419 os << "\\usepackage[" << from_ascii(font_encoding())
1420 << ",LFE,LAE]{fontenc}\n";
1422 os << "\\usepackage[" << from_ascii(font_encoding())
1427 // handle inputenc etc.
1428 writeEncodingPreamble(os, features);
1431 if (!features.runparams().includeall && !included_children_.empty()) {
1432 os << "\\includeonly{";
1433 list<string>::const_iterator it = included_children_.begin();
1434 list<string>::const_iterator en = included_children_.end();
1436 for (; it != en; ++it) {
1437 string incfile = *it;
1438 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1439 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1441 if (!features.runparams().nice)
1443 // \includeonly doesn't want an extension
1444 incfile = changeExtension(incfile, string());
1445 incfile = support::latex_path(incfile);
1446 if (!incfile.empty()) {
1449 os << from_utf8(incfile);
1456 if (!listings_params.empty() || features.isRequired("listings"))
1457 os << "\\usepackage{listings}\n";
1459 if (!listings_params.empty()) {
1461 // do not test validity because listings_params is
1462 // supposed to be valid
1464 InsetListingsParams(listings_params).separatedParams(true);
1465 // we can't support all packages, but we should load the color package
1466 if (par.find("\\color", 0) != string::npos)
1467 features.require("color");
1468 os << from_utf8(par)
1471 if (!tclass.provides("geometry")
1472 && (use_geometry || nonstandard_papersize)) {
1473 odocstringstream ods;
1474 if (!getGraphicsDriver("geometry").empty())
1475 ods << getGraphicsDriver("geometry");
1476 if (orientation == ORIENTATION_LANDSCAPE)
1477 ods << ",landscape";
1478 switch (papersize) {
1480 if (!paperwidth.empty())
1481 ods << ",paperwidth="
1482 << from_ascii(paperwidth);
1483 if (!paperheight.empty())
1484 ods << ",paperheight="
1485 << from_ascii(paperheight);
1487 case PAPER_USLETTER:
1488 ods << ",letterpaper";
1491 ods << ",legalpaper";
1493 case PAPER_USEXECUTIVE:
1494 ods << ",executivepaper";
1583 docstring const g_options = trim(ods.str(), ",");
1584 os << "\\usepackage";
1585 if (!g_options.empty())
1586 os << '[' << g_options << ']';
1587 os << "{geometry}\n";
1588 // output this only if use_geometry is true
1590 os << "\\geometry{verbose";
1591 if (!topmargin.empty())
1592 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1593 if (!bottommargin.empty())
1594 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1595 if (!leftmargin.empty())
1596 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1597 if (!rightmargin.empty())
1598 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1599 if (!headheight.empty())
1600 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1601 if (!headsep.empty())
1602 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1603 if (!footskip.empty())
1604 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1605 if (!columnsep.empty())
1606 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1609 } else if (orientation == ORIENTATION_LANDSCAPE
1610 || papersize != PAPER_DEFAULT) {
1611 features.require("papersize");
1614 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1615 if (pagestyle == "fancy")
1616 os << "\\usepackage{fancyhdr}\n";
1617 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1620 // only output when the background color is not default
1621 if (isbackgroundcolor == true) {
1622 // only require color here, the background color will be defined
1623 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1625 features.require("color");
1626 features.require("pagecolor");
1629 // only output when the font color is not default
1630 if (isfontcolor == true) {
1631 // only require color here, the font color will be defined
1632 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1634 features.require("color");
1635 features.require("fontcolor");
1638 // Only if class has a ToC hierarchy
1639 if (tclass.hasTocLevels()) {
1640 if (secnumdepth != tclass.secnumdepth()) {
1641 os << "\\setcounter{secnumdepth}{"
1645 if (tocdepth != tclass.tocdepth()) {
1646 os << "\\setcounter{tocdepth}{"
1652 if (paragraph_separation) {
1653 // when skip separation
1654 switch (getDefSkip().kind()) {
1655 case VSpace::SMALLSKIP:
1656 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1658 case VSpace::MEDSKIP:
1659 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1661 case VSpace::BIGSKIP:
1662 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1664 case VSpace::LENGTH:
1665 os << "\\setlength{\\parskip}{"
1666 << from_utf8(getDefSkip().length().asLatexString())
1669 default: // should never happen // Then delete it.
1670 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1673 os << "\\setlength{\\parindent}{0pt}\n";
1675 // when separation by indentation
1676 // only output something when a width is given
1677 if (getIndentation().asLyXCommand() != "default") {
1678 os << "\\setlength{\\parindent}{"
1679 << from_utf8(getIndentation().asLatexCommand())
1684 // Now insert the LyX specific LaTeX commands...
1685 docstring lyxpreamble;
1686 features.resolveAlternatives();
1689 if (!output_sync_macro.empty())
1690 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1691 else if (features.runparams().flavor == OutputParams::LATEX)
1692 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1693 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1694 lyxpreamble += "\\synctex=-1\n";
1697 // due to interferences with babel and hyperref, the color package has to
1698 // be loaded (when it is not already loaded) before babel when hyperref
1699 // is used with the colorlinks option, see
1700 // http://www.lyx.org/trac/ticket/5291
1701 // we decided therefore to load color always before babel, see
1702 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1703 lyxpreamble += from_ascii(features.getColorOptions());
1705 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1707 && (features.isRequired("jurabib")
1708 || features.isRequired("hyperref")
1709 || features.isRequired("vietnamese")
1710 || features.isRequired("japanese"))) {
1712 lyxpreamble += from_utf8(features.getBabelPresettings());
1713 lyxpreamble += from_utf8(babelCall(language_options.str(),
1714 features.needBabelLangOptions())) + '\n';
1715 lyxpreamble += from_utf8(features.getBabelPostsettings());
1718 // The optional packages;
1719 lyxpreamble += from_ascii(features.getPackages());
1721 // Additional Indices
1722 if (features.isRequired("splitidx")) {
1723 IndicesList::const_iterator iit = indiceslist().begin();
1724 IndicesList::const_iterator iend = indiceslist().end();
1725 for (; iit != iend; ++iit) {
1726 lyxpreamble += "\\newindex[";
1727 lyxpreamble += iit->index();
1728 lyxpreamble += "]{";
1729 lyxpreamble += iit->shortcut();
1730 lyxpreamble += "}\n";
1735 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1738 // * Hyperref manual: "Make sure it comes last of your loaded
1739 // packages, to give it a fighting chance of not being over-written,
1740 // since its job is to redefine many LaTeX commands."
1741 // * Email from Heiko Oberdiek: "It is usually better to load babel
1742 // before hyperref. Then hyperref has a chance to detect babel.
1743 // * Has to be loaded before the "LyX specific LaTeX commands" to
1744 // avoid errors with algorithm floats.
1745 // use hyperref explicitly if it is required
1746 if (features.isRequired("hyperref")) {
1747 // pass what we have to stream here, since we need
1748 // to access the stream itself in PDFOptions.
1751 OutputParams tmp_params = features.runparams();
1752 pdfoptions().writeLaTeX(tmp_params, os,
1753 documentClass().provides("hyperref"));
1754 // set back for the rest
1755 lyxpreamble.clear();
1756 // correctly break URLs with hyperref and dvi output
1757 if (features.runparams().flavor == OutputParams::LATEX
1758 && features.isAvailable("breakurl"))
1759 lyxpreamble += "\\usepackage{breakurl}\n";
1760 } else if (features.isRequired("nameref"))
1761 // hyperref loads this automatically
1762 lyxpreamble += "\\usepackage{nameref}\n";
1764 // Will be surrounded by \makeatletter and \makeatother when not empty
1765 docstring atlyxpreamble;
1767 // Some macros LyX will need
1768 docstring tmppreamble(features.getMacros());
1770 if (!tmppreamble.empty())
1771 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1772 "LyX specific LaTeX commands.\n"
1773 + tmppreamble + '\n';
1775 // the text class specific preamble
1776 tmppreamble = features.getTClassPreamble();
1777 if (!tmppreamble.empty())
1778 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1779 "Textclass specific LaTeX commands.\n"
1780 + tmppreamble + '\n';
1782 // suppress date if selected
1783 // use \@ifundefined because we cannot be sure that every document class
1784 // has a \date command
1786 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1788 /* the user-defined preamble */
1789 if (!containsOnly(preamble, " \n\t"))
1791 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1792 "User specified LaTeX commands.\n"
1793 + from_utf8(preamble) + '\n';
1795 // subfig loads internally the LaTeX package "caption". As
1796 // caption is a very popular package, users will load it in
1797 // the preamble. Therefore we must load subfig behind the
1798 // user-defined preamble and check if the caption package was
1799 // loaded or not. For the case that caption is loaded before
1800 // subfig, there is the subfig option "caption=false". This
1801 // option also works when a koma-script class is used and
1802 // koma's own caption commands are used instead of caption. We
1803 // use \PassOptionsToPackage here because the user could have
1804 // already loaded subfig in the preamble.
1805 if (features.isRequired("subfig")) {
1806 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1807 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1808 "\\usepackage{subfig}\n";
1811 // Itemize bullet settings need to be last in case the user
1812 // defines their own bullets that use a package included
1813 // in the user-defined preamble -- ARRae
1814 // Actually it has to be done much later than that
1815 // since some packages like frenchb make modifications
1816 // at \begin{document} time -- JMarc
1817 docstring bullets_def;
1818 for (int i = 0; i < 4; ++i) {
1819 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1820 if (bullets_def.empty())
1821 bullets_def += "\\AtBeginDocument{\n";
1822 bullets_def += " \\def\\labelitemi";
1824 // `i' is one less than the item to modify
1831 bullets_def += "ii";
1837 bullets_def += '{' +
1838 user_defined_bullet(i).getText()
1843 if (!bullets_def.empty())
1844 atlyxpreamble += bullets_def + "}\n\n";
1846 if (!atlyxpreamble.empty())
1847 lyxpreamble += "\n\\makeatletter\n"
1848 + atlyxpreamble + "\\makeatother\n\n";
1850 // We try to load babel late, in case it interferes with other packages.
1851 // Jurabib and Hyperref have to be called after babel, though.
1852 if (use_babel && !features.isRequired("jurabib")
1853 && !features.isRequired("hyperref")
1854 && !features.isRequired("vietnamese")
1855 && !features.isRequired("japanese")) {
1857 lyxpreamble += from_utf8(features.getBabelPresettings());
1858 lyxpreamble += from_utf8(babelCall(language_options.str(),
1859 features.needBabelLangOptions())) + '\n';
1860 lyxpreamble += from_utf8(features.getBabelPostsettings());
1863 // xunicode needs to be loaded at least after amsmath, amssymb,
1864 // esint and the other packages that provide special glyphs
1865 if (features.runparams().flavor == OutputParams::XETEX)
1866 lyxpreamble += "\\usepackage{xunicode}\n";
1868 // Polyglossia must be loaded last
1869 if (use_polyglossia) {
1871 lyxpreamble += "\\usepackage{polyglossia}\n";
1872 // set the main language
1873 lyxpreamble += "\\setdefaultlanguage";
1874 if (!language->polyglossiaOpts().empty())
1875 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1876 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1877 // now setup the other languages
1878 std::map<std::string, std::string> const polylangs =
1879 features.getPolyglossiaLanguages();
1880 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1881 mit != polylangs.end() ; ++mit) {
1882 lyxpreamble += "\\setotherlanguage";
1883 if (!mit->second.empty())
1884 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1885 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
1889 docstring const i18npreamble =
1890 features.getTClassI18nPreamble(use_babel, use_polyglossia);
1891 if (!i18npreamble.empty())
1892 lyxpreamble += i18npreamble + '\n';
1900 void BufferParams::useClassDefaults()
1902 DocumentClass const & tclass = documentClass();
1904 sides = tclass.sides();
1905 columns = tclass.columns();
1906 pagestyle = tclass.pagestyle();
1907 use_default_options = true;
1908 // Only if class has a ToC hierarchy
1909 if (tclass.hasTocLevels()) {
1910 secnumdepth = tclass.secnumdepth();
1911 tocdepth = tclass.tocdepth();
1916 bool BufferParams::hasClassDefaults() const
1918 DocumentClass const & tclass = documentClass();
1920 return sides == tclass.sides()
1921 && columns == tclass.columns()
1922 && pagestyle == tclass.pagestyle()
1923 && use_default_options
1924 && secnumdepth == tclass.secnumdepth()
1925 && tocdepth == tclass.tocdepth();
1929 DocumentClass const & BufferParams::documentClass() const
1935 DocumentClass const * BufferParams::documentClassPtr() const
1941 void BufferParams::setDocumentClass(DocumentClass const * const tc)
1943 // evil, but this function is evil
1944 doc_class_ = const_cast<DocumentClass *>(tc);
1948 bool BufferParams::setBaseClass(string const & classname)
1950 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1951 LayoutFileList & bcl = LayoutFileList::get();
1952 if (!bcl.haveClass(classname)) {
1954 bformat(_("The layout file:\n"
1956 "could not be found. A default textclass with default\n"
1957 "layouts will be used. LyX will not be able to produce\n"
1959 from_utf8(classname));
1960 frontend::Alert::error(_("Document class not found"), s);
1961 bcl.addEmptyClass(classname);
1964 bool const success = bcl[classname].load();
1967 bformat(_("Due to some error in it, the layout file:\n"
1969 "could not be loaded. A default textclass with default\n"
1970 "layouts will be used. LyX will not be able to produce\n"
1972 from_utf8(classname));
1973 frontend::Alert::error(_("Could not load class"), s);
1974 bcl.addEmptyClass(classname);
1977 pimpl_->baseClass_ = classname;
1978 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
1983 LayoutFile const * BufferParams::baseClass() const
1985 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1986 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1992 LayoutFileIndex const & BufferParams::baseClassID() const
1994 return pimpl_->baseClass_;
1998 void BufferParams::makeDocumentClass()
2003 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layout_modules_));
2005 if (!local_layout.empty()) {
2006 TextClass::ReturnValues success =
2007 doc_class_->read(local_layout, TextClass::MODULE);
2008 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2009 docstring const msg = _("Error reading internal layout information");
2010 frontend::Alert::warning(_("Read Error"), msg);
2016 bool BufferParams::moduleCanBeAdded(string const & modName) const
2018 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2022 bool BufferParams::addLayoutModule(string const & modName)
2024 LayoutModuleList::const_iterator it = layout_modules_.begin();
2025 LayoutModuleList::const_iterator end = layout_modules_.end();
2026 for (; it != end; it++)
2029 layout_modules_.push_back(modName);
2034 string BufferParams::bufferFormat() const
2036 string format = documentClass().outputFormat();
2037 if (format == "latex") {
2040 if (encoding().package() == Encoding::japanese)
2047 bool BufferParams::isExportable(string const & format) const
2049 vector<string> backs = backends();
2050 for (vector<string>::const_iterator it = backs.begin();
2051 it != backs.end(); ++it)
2052 if (theConverters().isReachable(*it, format))
2059 bool formatSorter(Format const * lhs, Format const * rhs) {
2060 return _(lhs->prettyname()) < _(rhs->prettyname());
2065 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2067 vector<string> const backs = backends();
2068 set<string> excludes;
2069 if (useNonTeXFonts) {
2070 excludes.insert("latex");
2071 excludes.insert("pdflatex");
2073 vector<Format const *> result =
2074 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2075 for (vector<string>::const_iterator it = backs.begin() + 1;
2076 it != backs.end(); ++it) {
2077 vector<Format const *> r =
2078 theConverters().getReachable(*it, only_viewable, false, excludes);
2079 result.insert(result.end(), r.begin(), r.end());
2081 sort(result.begin(), result.end(), formatSorter);
2086 bool BufferParams::isExportableFormat(string const & format) const
2088 typedef vector<Format const *> Formats;
2090 formats = exportableFormats(true);
2091 Formats::const_iterator fit = formats.begin();
2092 Formats::const_iterator end = formats.end();
2093 for (; fit != end ; ++fit) {
2094 if ((*fit)->name() == format)
2101 vector<string> BufferParams::backends() const
2104 v.push_back(bufferFormat());
2105 // FIXME: Don't hardcode format names here, but use a flag
2106 if (v.back() == "latex") {
2107 v.push_back("pdflatex");
2108 v.push_back("luatex");
2109 v.push_back("dviluatex");
2110 v.push_back("xetex");
2111 } else if (v.back() == "xetex") {
2112 v.push_back("luatex");
2113 v.push_back("dviluatex");
2115 v.push_back("xhtml");
2116 v.push_back("text");
2122 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const format) const
2124 string const dformat = (format.empty() || format == "default") ?
2125 getDefaultOutputFormat() : format;
2126 DefaultFlavorCache::const_iterator it =
2127 default_flavors_.find(dformat);
2129 if (it != default_flavors_.end())
2132 OutputParams::FLAVOR result = OutputParams::LATEX;
2134 if (dformat == "xhtml")
2135 result = OutputParams::HTML;
2137 // Try to determine flavor of default output format
2138 vector<string> backs = backends();
2139 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2140 // Get shortest path to format
2141 Graph::EdgePath path;
2142 for (vector<string>::const_iterator it = backs.begin();
2143 it != backs.end(); ++it) {
2144 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2145 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2150 result = theConverters().getFlavor(path);
2153 // cache this flavor
2154 default_flavors_[dformat] = result;
2159 string BufferParams::getDefaultOutputFormat() const
2161 if (!default_output_format.empty()
2162 && default_output_format != "default")
2163 return default_output_format;
2166 || encoding().package() == Encoding::japanese) {
2167 vector<Format const *> const formats = exportableFormats(true);
2168 if (formats.empty())
2170 // return the first we find
2171 return formats.front()->name();
2173 return lyxrc.default_view_format;
2176 Font const BufferParams::getFont() const
2178 FontInfo f = documentClass().defaultfont();
2179 if (fonts_default_family == "rmdefault")
2180 f.setFamily(ROMAN_FAMILY);
2181 else if (fonts_default_family == "sfdefault")
2182 f.setFamily(SANS_FAMILY);
2183 else if (fonts_default_family == "ttdefault")
2184 f.setFamily(TYPEWRITER_FAMILY);
2185 return Font(f, language);
2189 bool BufferParams::isLatex() const
2191 return documentClass().outputType() == LATEX;
2195 bool BufferParams::isLiterate() const
2197 return documentClass().outputType() == LITERATE;
2201 bool BufferParams::isDocBook() const
2203 return documentClass().outputType() == DOCBOOK;
2207 void BufferParams::readPreamble(Lexer & lex)
2209 if (lex.getString() != "\\begin_preamble")
2210 lyxerr << "Error (BufferParams::readPreamble):"
2211 "consistency check failed." << endl;
2213 preamble = lex.getLongString("\\end_preamble");
2217 void BufferParams::readLocalLayout(Lexer & lex)
2219 if (lex.getString() != "\\begin_local_layout")
2220 lyxerr << "Error (BufferParams::readLocalLayout):"
2221 "consistency check failed." << endl;
2223 local_layout = lex.getLongString("\\end_local_layout");
2227 bool BufferParams::setLanguage(string const & lang)
2229 Language const *new_language = languages.getLanguage(lang);
2230 if (!new_language) {
2231 // Language lang was not found
2234 language = new_language;
2239 void BufferParams::readLanguage(Lexer & lex)
2241 if (!lex.next()) return;
2243 string const tmptok = lex.getString();
2245 // check if tmptok is part of tex_babel in tex-defs.h
2246 if (!setLanguage(tmptok)) {
2247 // Language tmptok was not found
2248 language = default_language;
2249 lyxerr << "Warning: Setting language `"
2250 << tmptok << "' to `" << language->lang()
2256 void BufferParams::readGraphicsDriver(Lexer & lex)
2261 string const tmptok = lex.getString();
2262 // check if tmptok is part of tex_graphics in tex_defs.h
2265 string const test = tex_graphics[n++];
2267 if (test == tmptok) {
2268 graphics_driver = tmptok;
2273 "Warning: graphics driver `$$Token' not recognized!\n"
2274 " Setting graphics driver to `default'.\n");
2275 graphics_driver = "default";
2282 void BufferParams::readBullets(Lexer & lex)
2287 int const index = lex.getInteger();
2289 int temp_int = lex.getInteger();
2290 user_defined_bullet(index).setFont(temp_int);
2291 temp_bullet(index).setFont(temp_int);
2293 user_defined_bullet(index).setCharacter(temp_int);
2294 temp_bullet(index).setCharacter(temp_int);
2296 user_defined_bullet(index).setSize(temp_int);
2297 temp_bullet(index).setSize(temp_int);
2301 void BufferParams::readBulletsLaTeX(Lexer & lex)
2303 // The bullet class should be able to read this.
2306 int const index = lex.getInteger();
2308 docstring const temp_str = lex.getDocString();
2310 user_defined_bullet(index).setText(temp_str);
2311 temp_bullet(index).setText(temp_str);
2315 void BufferParams::readModules(Lexer & lex)
2317 if (!lex.eatLine()) {
2318 lyxerr << "Error (BufferParams::readModules):"
2319 "Unexpected end of input." << endl;
2323 string mod = lex.getString();
2324 if (mod == "\\end_modules")
2326 addLayoutModule(mod);
2332 void BufferParams::readRemovedModules(Lexer & lex)
2334 if (!lex.eatLine()) {
2335 lyxerr << "Error (BufferParams::readRemovedModules):"
2336 "Unexpected end of input." << endl;
2340 string mod = lex.getString();
2341 if (mod == "\\end_removed_modules")
2343 removed_modules_.push_back(mod);
2346 // now we want to remove any removed modules that were previously
2347 // added. normally, that will be because default modules were added in
2348 // setBaseClass(), which gets called when \textclass is read at the
2349 // start of the read.
2350 list<string>::const_iterator rit = removed_modules_.begin();
2351 list<string>::const_iterator const ren = removed_modules_.end();
2352 for (; rit != ren; rit++) {
2353 LayoutModuleList::iterator const mit = layout_modules_.begin();
2354 LayoutModuleList::iterator const men = layout_modules_.end();
2355 LayoutModuleList::iterator found = find(mit, men, *rit);
2358 layout_modules_.erase(found);
2363 void BufferParams::readIncludeonly(Lexer & lex)
2365 if (!lex.eatLine()) {
2366 lyxerr << "Error (BufferParams::readIncludeonly):"
2367 "Unexpected end of input." << endl;
2371 string child = lex.getString();
2372 if (child == "\\end_includeonly")
2374 included_children_.push_back(child);
2380 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2382 switch (papersize) {
2384 // could be anything, so don't guess
2386 case PAPER_CUSTOM: {
2387 if (purpose == XDVI && !paperwidth.empty() &&
2388 !paperheight.empty()) {
2389 // heightxwidth<unit>
2390 string first = paperwidth;
2391 string second = paperheight;
2392 if (orientation == ORIENTATION_LANDSCAPE)
2395 return first.erase(first.length() - 2)
2401 // dvips and dvipdfm do not know this
2402 if (purpose == DVIPS || purpose == DVIPDFM)
2406 if (purpose == DVIPS || purpose == DVIPDFM)
2410 if (purpose == DVIPS || purpose == DVIPDFM)
2420 if (purpose == DVIPS || purpose == DVIPDFM)
2424 if (purpose == DVIPS || purpose == DVIPDFM)
2428 if (purpose == DVIPS || purpose == DVIPDFM)
2432 if (purpose == DVIPS || purpose == DVIPDFM)
2436 if (purpose == DVIPS || purpose == DVIPDFM)
2440 // dvipdfm does not know this
2441 if (purpose == DVIPDFM)
2445 if (purpose == DVIPDFM)
2449 if (purpose == DVIPS || purpose == DVIPDFM)
2453 if (purpose == DVIPS || purpose == DVIPDFM)
2457 if (purpose == DVIPS || purpose == DVIPDFM)
2461 if (purpose == DVIPS || purpose == DVIPDFM)
2465 if (purpose == DVIPS || purpose == DVIPDFM)
2469 if (purpose == DVIPS || purpose == DVIPDFM)
2473 if (purpose == DVIPS || purpose == DVIPDFM)
2477 if (purpose == DVIPS || purpose == DVIPDFM)
2481 if (purpose == DVIPS || purpose == DVIPDFM)
2485 if (purpose == DVIPS || purpose == DVIPDFM)
2489 if (purpose == DVIPS || purpose == DVIPDFM)
2493 if (purpose == DVIPS || purpose == DVIPDFM)
2497 if (purpose == DVIPS || purpose == DVIPDFM)
2501 if (purpose == DVIPS || purpose == DVIPDFM)
2505 if (purpose == DVIPS || purpose == DVIPDFM)
2508 case PAPER_USEXECUTIVE:
2509 // dvipdfm does not know this
2510 if (purpose == DVIPDFM)
2515 case PAPER_USLETTER:
2517 if (purpose == XDVI)
2524 string const BufferParams::dvips_options() const
2529 && papersize == PAPER_CUSTOM
2530 && !lyxrc.print_paper_dimension_flag.empty()
2531 && !paperwidth.empty()
2532 && !paperheight.empty()) {
2533 // using a custom papersize
2534 result = lyxrc.print_paper_dimension_flag;
2535 result += ' ' + paperwidth;
2536 result += ',' + paperheight;
2538 string const paper_option = paperSizeName(DVIPS);
2539 if (!paper_option.empty() && (paper_option != "letter" ||
2540 orientation != ORIENTATION_LANDSCAPE)) {
2541 // dvips won't accept -t letter -t landscape.
2542 // In all other cases, include the paper size
2544 result = lyxrc.print_paper_flag;
2545 result += ' ' + paper_option;
2548 if (orientation == ORIENTATION_LANDSCAPE &&
2549 papersize != PAPER_CUSTOM)
2550 result += ' ' + lyxrc.print_landscape_flag;
2555 string const BufferParams::font_encoding() const
2557 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2561 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2563 if (lang_package != "auto" && lang_package != "babel"
2564 && lang_package != "default" && lang_package != "none")
2565 return lang_package;
2566 if (lyxrc.language_package_selection == LyXRC::LP_CUSTOM)
2567 return lyxrc.language_custom_package;
2568 // suppress the babel call if there is no BabelName defined
2569 // for the document language in the lib/languages file and if no
2570 // other languages are used (lang_opts is then empty)
2571 if (lang_opts.empty())
2573 // either a specific language (AsBabelOptions setting in
2574 // lib/languages) or the prefs require the languages to
2575 // be submitted to babel itself (not the class).
2577 return "\\usepackage[" + lang_opts + "]{babel}";
2578 return "\\usepackage{babel}";
2582 docstring BufferParams::getGraphicsDriver(string const & package) const
2586 if (package == "geometry") {
2587 if (graphics_driver == "dvips"
2588 || graphics_driver == "dvipdfm"
2589 || graphics_driver == "pdftex"
2590 || graphics_driver == "vtex")
2591 result = from_ascii(graphics_driver);
2592 else if (graphics_driver == "dvipdfmx")
2593 result = from_ascii("dvipdfm");
2600 void BufferParams::writeEncodingPreamble(otexstream & os,
2601 LaTeXFeatures & features) const
2603 // XeTeX does not need this
2604 if (features.runparams().flavor == OutputParams::XETEX)
2606 // LuaTeX neither, but with tex fonts, we need to load
2607 // the luainputenc package.
2608 if (features.runparams().flavor == OutputParams::LUATEX
2609 || features.runparams().flavor == OutputParams::DVILUATEX) {
2610 if (!useNonTeXFonts && inputenc != "default"
2611 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2612 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2613 os << "\\usepackage[utf8]{luainputenc}\n";
2617 if (inputenc == "auto") {
2618 string const doc_encoding =
2619 language->encoding()->latexName();
2620 Encoding::Package const package =
2621 language->encoding()->package();
2623 // Create a list with all the input encodings used
2625 set<string> encodings =
2626 features.getEncodingSet(doc_encoding);
2628 // If the "japanese" package (i.e. pLaTeX) is used,
2629 // inputenc must be omitted.
2630 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2631 if (package == Encoding::japanese)
2632 features.require("japanese");
2634 if ((!encodings.empty() || package == Encoding::inputenc)
2635 && !features.isRequired("japanese")) {
2636 os << "\\usepackage[";
2637 set<string>::const_iterator it = encodings.begin();
2638 set<string>::const_iterator const end = encodings.end();
2640 os << from_ascii(*it);
2643 for (; it != end; ++it)
2644 os << ',' << from_ascii(*it);
2645 if (package == Encoding::inputenc) {
2646 if (!encodings.empty())
2648 os << from_ascii(doc_encoding);
2650 os << "]{inputenc}\n";
2652 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2653 if (language->encoding()->name() == "utf8-cjk"
2654 && LaTeXFeatures::isAvailable("CJKutf8"))
2655 os << "\\usepackage{CJKutf8}\n";
2657 os << "\\usepackage{CJK}\n";
2659 } else if (inputenc != "default") {
2660 switch (encoding().package()) {
2661 case Encoding::none:
2662 case Encoding::japanese:
2664 case Encoding::inputenc:
2665 // do not load inputenc if japanese is used
2666 if (features.isRequired("japanese"))
2668 os << "\\usepackage[" << from_ascii(inputenc)
2672 if (encoding().name() == "utf8-cjk"
2673 && LaTeXFeatures::isAvailable("CJKutf8"))
2674 os << "\\usepackage{CJKutf8}\n";
2676 os << "\\usepackage{CJK}\n";
2681 // The encoding "armscii8" (for Armenian) is only available when
2682 // the package "armtex" is loaded.
2683 if (language->encoding()->latexName() == "armscii8"
2684 || inputenc == "armscii8")
2685 os << "\\usepackage{armtex}\n";
2689 string const BufferParams::parseFontName(string const & name) const
2691 string mangled = name;
2692 size_t const idx = mangled.find('[');
2693 if (idx == string::npos || idx == 0)
2696 return mangled.substr(0, idx - 1);
2700 string const BufferParams::loadFonts(string const & rm,
2701 string const & sf, string const & tt,
2702 bool const & sc, bool const & osf,
2703 int const & sfscale, int const & ttscale,
2704 bool const & use_systemfonts,
2705 LaTeXFeatures & features) const
2707 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2708 several packages have been replaced by others, that might not
2709 be installed on every system. We have to take care for that
2710 (see psnfss.pdf). We try to support all psnfss fonts as well
2711 as the fonts that have become de facto standard in the LaTeX
2712 world (e.g. Latin Modern). We do not support obsolete fonts
2713 (like PSLatex). In general, it should be possible to mix any
2714 rm font with any sf or tt font, respectively. (JSpitzm)
2716 -- separate math fonts.
2719 if (rm == "default" && sf == "default" && tt == "default")
2725 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2726 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2727 * Mapping=tex-text option assures TeX ligatures (such as "--")
2728 * are resolved. Note that tt does not use these ligatures.
2730 * -- add more GUI options?
2731 * -- add more fonts (fonts for other scripts)
2732 * -- if there's a way to find out if a font really supports
2733 * OldStyle, enable/disable the widget accordingly.
2735 if (use_systemfonts && features.isAvailable("fontspec")) {
2736 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2737 // However, until v.2 (2010/07/11) fontspec only knew
2738 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2739 // was introduced for both XeTeX and LuaTeX (LuaTeX
2740 // didn't understand "Mapping=tex-text", while XeTeX
2741 // understood both. With most recent versions, both
2742 // variants are understood by both engines. However,
2743 // we want to provide support for at least TeXLive 2009
2744 // (for XeTeX; LuaTeX is only supported as of v.2)
2745 string const texmapping =
2746 (features.runparams().flavor == OutputParams::XETEX) ?
2747 "Mapping=tex-text" : "Ligatures=TeX";
2748 if (rm != "default") {
2749 os << "\\setmainfont[" << texmapping;
2751 os << ",Numbers=OldStyle";
2752 os << "]{" << parseFontName(rm) << "}\n";
2754 if (sf != "default") {
2755 string const sans = parseFontName(sf);
2757 os << "\\setsansfont[Scale="
2758 << float(sfscale) / 100
2759 << "," << texmapping << "]{"
2762 os << "\\setsansfont[" << texmapping << "]{"
2765 if (tt != "default") {
2766 string const mono = parseFontName(tt);
2768 os << "\\setmonofont[Scale="
2769 << float(ttscale) / 100
2773 os << "\\setmonofont{"
2780 // Computer Modern (must be explicitly selectable -- there might be classes
2781 // that define a different default font!
2783 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2784 // osf for Computer Modern needs eco.sty
2786 os << "\\usepackage{eco}\n";
2788 // Latin Modern Roman
2789 else if (rm == "lmodern")
2790 os << "\\usepackage{lmodern}\n";
2792 else if (rm == "ae") {
2793 // not needed when using OT1 font encoding.
2794 if (font_encoding() != "default")
2795 os << "\\usepackage{ae,aecompl}\n";
2798 else if (rm == "times") {
2799 // try to load the best available package
2800 if (LaTeXFeatures::isAvailable("mathptmx"))
2801 os << "\\usepackage{mathptmx}\n";
2802 else if (LaTeXFeatures::isAvailable("mathptm"))
2803 os << "\\usepackage{mathptm}\n";
2805 os << "\\usepackage{times}\n";
2808 else if (rm == "palatino") {
2809 // try to load the best available package
2810 if (LaTeXFeatures::isAvailable("mathpazo")) {
2811 os << "\\usepackage";
2817 // "osf" includes "sc"!
2821 os << "{mathpazo}\n";
2823 else if (LaTeXFeatures::isAvailable("mathpple"))
2824 os << "\\usepackage{mathpple}\n";
2826 os << "\\usepackage{palatino}\n";
2829 else if (rm == "utopia") {
2830 // fourier supersedes utopia.sty, but does
2831 // not work with OT1 encoding.
2832 if (LaTeXFeatures::isAvailable("fourier")
2833 && font_encoding() != "default") {
2834 os << "\\usepackage";
2845 os << "{fourier}\n";
2848 os << "\\usepackage{utopia}\n";
2850 // Bera (complete fontset)
2851 else if (rm == "bera" && sf == "default" && tt == "default")
2852 os << "\\usepackage{bera}\n";
2854 else if (rm != "default")
2855 os << "\\usepackage" << "{" << rm << "}\n";
2858 // Helvetica, Bera Sans
2859 if (sf == "helvet" || sf == "berasans") {
2861 os << "\\usepackage[scaled=" << float(sfscale) / 100
2862 << "]{" << sf << "}\n";
2864 os << "\\usepackage{" << sf << "}\n";
2867 else if (sf == "avant")
2868 os << "\\usepackage{" << sf << "}\n";
2869 // Computer Modern, Latin Modern, CM Bright
2870 else if (sf != "default")
2871 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2873 // monospaced/typewriter
2874 // Courier, LuxiMono
2875 if (tt == "luximono" || tt == "beramono") {
2877 os << "\\usepackage[scaled=" << float(ttscale) / 100
2878 << "]{" << tt << "}\n";
2880 os << "\\usepackage{" << tt << "}\n";
2883 else if (tt == "courier" )
2884 os << "\\usepackage{" << tt << "}\n";
2885 // Computer Modern, Latin Modern, CM Bright
2886 else if (tt != "default")
2887 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2893 Encoding const & BufferParams::encoding() const
2895 // FIXME: actually, we should check for the flavor
2896 // or runparams.isFullyUnicode() here:
2897 // This check will not work with XeTeX/LuaTeX and tex fonts.
2898 // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2900 return *(encodings.fromLaTeXName("utf8-plain"));
2901 if (inputenc == "auto" || inputenc == "default")
2902 return *language->encoding();
2903 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2906 LYXERR0("Unknown inputenc value `" << inputenc
2907 << "'. Using `auto' instead.");
2908 return *language->encoding();
2912 CiteEngine BufferParams::citeEngine() const
2914 // FIXME the class should provide the numerical/
2915 // authoryear choice
2916 if (documentClass().provides("natbib")
2917 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2918 return ENGINE_NATBIB_AUTHORYEAR;
2919 return cite_engine_;
2923 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2925 cite_engine_ = cite_engine;