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 cite_engine_ = ENGINE_BASIC;
369 use_bibtopic = false;
371 trackChanges = false;
372 outputChanges = false;
373 use_default_options = true;
374 maintain_unincluded_children = false;
377 language = default_language;
379 fonts_roman = "default";
380 fonts_sans = "default";
381 fonts_typewriter = "default";
382 fonts_default_family = "default";
383 useNonTeXFonts = false;
384 fonts_expert_sc = false;
385 fonts_old_figures = false;
386 fonts_sans_scale = 100;
387 fonts_typewriter_scale = 100;
389 lang_package = "default";
390 graphics_driver = "default";
391 default_output_format = "default";
392 bibtex_command = "default";
393 index_command = "default";
396 listings_params = string();
397 pagestyle = "default";
398 suppress_date = false;
399 // no color is the default (white)
400 backgroundcolor = lyx::rgbFromHexName("#ffffff");
401 isbackgroundcolor = false;
402 // no color is the default (black)
403 fontcolor = lyx::rgbFromHexName("#000000");
405 // light gray is the default font color for greyed-out notes
406 notefontcolor = lyx::rgbFromHexName("#cccccc");
407 boxbgcolor = lyx::rgbFromHexName("#ff0000");
408 compressed = lyxrc.save_compressed;
409 for (int iter = 0; iter < 4; ++iter) {
410 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
411 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
414 indiceslist().addDefault(B_("Index"));
415 html_be_strict = false;
416 html_math_output = MathML;
417 html_math_img_scale = 1.0;
418 html_css_as_file = false;
425 docstring BufferParams::B_(string const & l10n) const
427 LASSERT(language, /**/);
428 return getMessages(language->code()).get(l10n);
432 AuthorList & BufferParams::authors()
434 return pimpl_->authorlist;
438 AuthorList const & BufferParams::authors() const
440 return pimpl_->authorlist;
444 BranchList & BufferParams::branchlist()
446 return pimpl_->branchlist;
450 BranchList const & BufferParams::branchlist() const
452 return pimpl_->branchlist;
456 IndicesList & BufferParams::indiceslist()
458 return pimpl_->indiceslist;
462 IndicesList const & BufferParams::indiceslist() const
464 return pimpl_->indiceslist;
468 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
470 LASSERT(index < 4, /**/);
471 return pimpl_->temp_bullets[index];
475 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
477 LASSERT(index < 4, /**/);
478 return pimpl_->temp_bullets[index];
482 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
484 LASSERT(index < 4, /**/);
485 return pimpl_->user_defined_bullets[index];
489 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
491 LASSERT(index < 4, /**/);
492 return pimpl_->user_defined_bullets[index];
496 Spacing & BufferParams::spacing()
498 return pimpl_->spacing;
502 Spacing const & BufferParams::spacing() const
504 return pimpl_->spacing;
508 PDFOptions & BufferParams::pdfoptions()
510 return pimpl_->pdfoptions;
514 PDFOptions const & BufferParams::pdfoptions() const
516 return pimpl_->pdfoptions;
520 HSpace const & BufferParams::getIndentation() const
522 return pimpl_->indentation;
526 void BufferParams::setIndentation(HSpace const & indent)
528 pimpl_->indentation = indent;
532 VSpace const & BufferParams::getDefSkip() const
534 return pimpl_->defskip;
538 void BufferParams::setDefSkip(VSpace const & vs)
540 // DEFSKIP will cause an infinite loop
541 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
542 pimpl_->defskip = vs;
546 string BufferParams::readToken(Lexer & lex, string const & token,
547 FileName const & filepath)
549 if (token == "\\textclass") {
551 string const classname = lex.getString();
552 // if there exists a local layout file, ignore the system one
553 // NOTE: in this case, the textclass (.cls file) is assumed to
556 LayoutFileList & bcl = LayoutFileList::get();
557 if (tcp.empty() && !filepath.empty())
558 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
562 setBaseClass(classname);
563 // We assume that a tex class exists for local or unknown
564 // layouts so this warning, will only be given for system layouts.
565 if (!baseClass()->isTeXClassAvailable()) {
566 docstring const desc =
567 translateIfPossible(from_utf8(baseClass()->description()));
568 docstring const prereqs =
569 from_utf8(baseClass()->prerequisites());
570 docstring const msg =
571 bformat(_("The selected document class\n"
573 "requires external files that are not available.\n"
574 "The document class can still be used, but the\n"
575 "document cannot be compiled until the following\n"
576 "prerequisites are installed:\n"
578 "See section 3.1.2.2 (Class Availability) of the\n"
579 "User's Guide for more information."), desc, prereqs);
580 frontend::Alert::warning(_("Document class not available"),
583 } else if (token == "\\begin_preamble") {
585 } else if (token == "\\begin_local_layout") {
586 readLocalLayout(lex);
587 } else if (token == "\\begin_modules") {
589 } else if (token == "\\begin_removed_modules") {
590 readRemovedModules(lex);
591 } else if (token == "\\begin_includeonly") {
592 readIncludeonly(lex);
593 } else if (token == "\\maintain_unincluded_children") {
594 lex >> maintain_unincluded_children;
595 } else if (token == "\\options") {
597 options = lex.getString();
598 } else if (token == "\\use_default_options") {
599 lex >> use_default_options;
600 } else if (token == "\\master") {
602 master = lex.getString();
603 } else if (token == "\\suppress_date") {
604 lex >> suppress_date;
605 } else if (token == "\\language") {
607 } else if (token == "\\language_package") {
609 lang_package = lex.getString();
610 } else if (token == "\\inputencoding") {
612 } else if (token == "\\graphics") {
613 readGraphicsDriver(lex);
614 } else if (token == "\\default_output_format") {
615 lex >> default_output_format;
616 } else if (token == "\\bibtex_command") {
618 bibtex_command = lex.getString();
619 } else if (token == "\\index_command") {
621 index_command = lex.getString();
622 } else if (token == "\\fontencoding") {
624 fontenc = lex.getString();
625 } else if (token == "\\font_roman") {
627 fonts_roman = lex.getString();
628 } else if (token == "\\font_sans") {
630 fonts_sans = lex.getString();
631 } else if (token == "\\font_typewriter") {
633 fonts_typewriter = lex.getString();
634 } else if (token == "\\font_default_family") {
635 lex >> fonts_default_family;
636 } else if (token == "\\use_non_tex_fonts") {
637 lex >> useNonTeXFonts;
638 } else if (token == "\\font_sc") {
639 lex >> fonts_expert_sc;
640 } else if (token == "\\font_osf") {
641 lex >> fonts_old_figures;
642 } else if (token == "\\font_sf_scale") {
643 lex >> fonts_sans_scale;
644 } else if (token == "\\font_tt_scale") {
645 lex >> fonts_typewriter_scale;
646 } else if (token == "\\font_cjk") {
648 } else if (token == "\\paragraph_separation") {
651 paragraph_separation = parseptranslator().find(parsep);
652 } else if (token == "\\paragraph_indentation") {
654 string indentation = lex.getString();
655 pimpl_->indentation = HSpace(indentation);
656 } else if (token == "\\defskip") {
658 string const defskip = lex.getString();
659 pimpl_->defskip = VSpace(defskip);
660 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
662 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
663 } else if (token == "\\quotes_language") {
666 quotes_language = quoteslangtranslator().find(quotes_lang);
667 } else if (token == "\\papersize") {
670 papersize = papersizetranslator().find(ppsize);
671 } else if (token == "\\use_geometry") {
673 } else if (token == "\\use_amsmath") {
676 use_amsmath = packagetranslator().find(use_ams);
677 } else if (token == "\\use_esint") {
680 use_esint = packagetranslator().find(useesint);
681 } else if (token == "\\use_mhchem") {
684 use_mhchem = packagetranslator().find(usemhchem);
685 } else if (token == "\\use_mathdots") {
688 use_mathdots = packagetranslator().find(usemathdots);
689 } else if (token == "\\cite_engine") {
692 cite_engine_ = citeenginetranslator().find(engine);
693 } else if (token == "\\use_bibtopic") {
695 } else if (token == "\\use_indices") {
697 } else if (token == "\\tracking_changes") {
699 } else if (token == "\\output_changes") {
700 lex >> outputChanges;
701 } else if (token == "\\branch") {
703 docstring branch = lex.getDocString();
704 branchlist().add(branch);
707 string const tok = lex.getString();
708 if (tok == "\\end_branch")
710 Branch * branch_ptr = branchlist().find(branch);
711 if (tok == "\\selected") {
714 branch_ptr->setSelected(lex.getInteger());
716 if (tok == "\\filename_suffix") {
719 branch_ptr->setFileNameSuffix(lex.getInteger());
721 if (tok == "\\color") {
723 string color = lex.getString();
725 branch_ptr->setColor(color);
726 // Update also the Color table:
728 color = lcolor.getX11Name(Color_background);
730 lcolor.setColor(to_utf8(branch), color);
733 } else if (token == "\\index") {
735 docstring index = lex.getDocString();
737 indiceslist().add(index);
740 string const tok = lex.getString();
741 if (tok == "\\end_index")
743 Index * index_ptr = indiceslist().find(index);
744 if (tok == "\\shortcut") {
746 shortcut = lex.getDocString();
748 index_ptr->setShortcut(shortcut);
750 if (tok == "\\color") {
752 string color = lex.getString();
754 index_ptr->setColor(color);
755 // Update also the Color table:
757 color = lcolor.getX11Name(Color_background);
759 if (!shortcut.empty())
760 lcolor.setColor(to_utf8(shortcut), color);
763 } else if (token == "\\author") {
765 istringstream ss(lex.getString());
768 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
769 } else if (token == "\\paperorientation") {
772 orientation = paperorientationtranslator().find(orient);
773 } else if (token == "\\backgroundcolor") {
775 backgroundcolor = lyx::rgbFromHexName(lex.getString());
776 isbackgroundcolor = true;
777 } else if (token == "\\fontcolor") {
779 fontcolor = lyx::rgbFromHexName(lex.getString());
781 } else if (token == "\\notefontcolor") {
783 string color = lex.getString();
784 notefontcolor = lyx::rgbFromHexName(color);
785 } else if (token == "\\boxbgcolor") {
787 string color = lex.getString();
788 boxbgcolor = lyx::rgbFromHexName(color);
789 } else if (token == "\\paperwidth") {
791 } else if (token == "\\paperheight") {
793 } else if (token == "\\leftmargin") {
795 } else if (token == "\\topmargin") {
797 } else if (token == "\\rightmargin") {
799 } else if (token == "\\bottommargin") {
801 } else if (token == "\\headheight") {
803 } else if (token == "\\headsep") {
805 } else if (token == "\\footskip") {
807 } else if (token == "\\columnsep") {
809 } else if (token == "\\paperfontsize") {
811 } else if (token == "\\papercolumns") {
813 } else if (token == "\\listings_params") {
816 listings_params = InsetListingsParams(par).params();
817 } else if (token == "\\papersides") {
820 sides = sidestranslator().find(psides);
821 } else if (token == "\\paperpagestyle") {
823 } else if (token == "\\bullet") {
825 } else if (token == "\\bulletLaTeX") {
826 readBulletsLaTeX(lex);
827 } else if (token == "\\secnumdepth") {
829 } else if (token == "\\tocdepth") {
831 } else if (token == "\\spacing") {
835 if (nspacing == "other") {
838 spacing().set(spacetranslator().find(nspacing), tmp_val);
839 } else if (token == "\\float_placement") {
840 lex >> float_placement;
842 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
843 string toktmp = pdfoptions().readToken(lex, token);
844 if (!toktmp.empty()) {
845 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
849 } else if (token == "\\html_math_output") {
852 html_math_output = static_cast<MathOutput>(temp);
853 } else if (token == "\\html_be_strict") {
854 lex >> html_be_strict;
855 } else if (token == "\\html_css_as_file") {
856 lex >> html_css_as_file;
857 } else if (token == "\\html_math_img_scale") {
858 lex >> html_math_img_scale;
859 } else if (token == "\\html_latex_start") {
861 html_latex_start = lex.getString();
862 } else if (token == "\\html_latex_end") {
864 html_latex_end = lex.getString();
865 } else if (token == "\\output_sync") {
867 } else if (token == "\\output_sync_macro") {
868 lex >> output_sync_macro;
869 } else if (token == "\\use_refstyle") {
872 lyxerr << "BufferParams::readToken(): Unknown token: " <<
881 void BufferParams::writeFile(ostream & os) const
883 // The top of the file is written by the buffer.
884 // Prints out the buffer info into the .lyx file given by file
887 os << "\\textclass " << baseClass()->name() << '\n';
890 if (!preamble.empty()) {
891 // remove '\n' from the end of preamble
892 string const tmppreamble = rtrim(preamble, "\n");
893 os << "\\begin_preamble\n"
895 << "\n\\end_preamble\n";
899 if (!options.empty()) {
900 os << "\\options " << options << '\n';
903 // use the class options defined in the layout?
904 os << "\\use_default_options "
905 << convert<string>(use_default_options) << "\n";
907 // the master document
908 if (!master.empty()) {
909 os << "\\master " << master << '\n';
913 if (!removed_modules_.empty()) {
914 os << "\\begin_removed_modules" << '\n';
915 list<string>::const_iterator it = removed_modules_.begin();
916 list<string>::const_iterator en = removed_modules_.end();
917 for (; it != en; it++)
919 os << "\\end_removed_modules" << '\n';
923 if (!layout_modules_.empty()) {
924 os << "\\begin_modules" << '\n';
925 LayoutModuleList::const_iterator it = layout_modules_.begin();
926 LayoutModuleList::const_iterator en = layout_modules_.end();
927 for (; it != en; it++)
929 os << "\\end_modules" << '\n';
933 if (!included_children_.empty()) {
934 os << "\\begin_includeonly" << '\n';
935 list<string>::const_iterator it = included_children_.begin();
936 list<string>::const_iterator en = included_children_.end();
937 for (; it != en; it++)
939 os << "\\end_includeonly" << '\n';
941 os << "\\maintain_unincluded_children "
942 << convert<string>(maintain_unincluded_children) << '\n';
944 // local layout information
945 if (!local_layout.empty()) {
946 // remove '\n' from the end
947 string const tmplocal = rtrim(local_layout, "\n");
948 os << "\\begin_local_layout\n"
950 << "\n\\end_local_layout\n";
953 // then the text parameters
954 if (language != ignore_language)
955 os << "\\language " << language->lang() << '\n';
956 os << "\\language_package " << lang_package
957 << "\n\\inputencoding " << inputenc
958 << "\n\\fontencoding " << fontenc
959 << "\n\\font_roman " << fonts_roman
960 << "\n\\font_sans " << fonts_sans
961 << "\n\\font_typewriter " << fonts_typewriter
962 << "\n\\font_default_family " << fonts_default_family
963 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
964 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
965 << "\n\\font_osf " << convert<string>(fonts_old_figures)
966 << "\n\\font_sf_scale " << fonts_sans_scale
967 << "\n\\font_tt_scale " << fonts_typewriter_scale
969 if (!fonts_cjk.empty()) {
970 os << "\\font_cjk " << fonts_cjk << '\n';
972 os << "\n\\graphics " << graphics_driver << '\n';
973 os << "\\default_output_format " << default_output_format << '\n';
974 os << "\\output_sync " << output_sync << '\n';
975 if (!output_sync_macro.empty())
976 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
977 os << "\\bibtex_command " << bibtex_command << '\n';
978 os << "\\index_command " << index_command << '\n';
980 if (!float_placement.empty()) {
981 os << "\\float_placement " << float_placement << '\n';
983 os << "\\paperfontsize " << fontsize << '\n';
985 spacing().writeFile(os);
986 pdfoptions().writeFile(os);
988 os << "\\papersize " << string_papersize[papersize]
989 << "\n\\use_geometry " << convert<string>(use_geometry)
990 << "\n\\use_amsmath " << use_amsmath
991 << "\n\\use_esint " << use_esint
992 << "\n\\use_mhchem " << use_mhchem
993 << "\n\\use_mathdots " << use_mathdots
994 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
995 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
996 << "\n\\use_indices " << convert<string>(use_indices)
997 << "\n\\paperorientation " << string_orientation[orientation]
998 << "\n\\suppress_date " << convert<string>(suppress_date)
999 << "\n\\use_refstyle " << use_refstyle
1001 if (isbackgroundcolor == true)
1002 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1003 if (isfontcolor == true)
1004 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1005 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1006 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1007 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1008 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1010 BranchList::const_iterator it = branchlist().begin();
1011 BranchList::const_iterator end = branchlist().end();
1012 for (; it != end; ++it) {
1013 os << "\\branch " << to_utf8(it->branch())
1014 << "\n\\selected " << it->isSelected()
1015 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1016 << "\n\\color " << lyx::X11hexname(it->color())
1021 IndicesList::const_iterator iit = indiceslist().begin();
1022 IndicesList::const_iterator iend = indiceslist().end();
1023 for (; iit != iend; ++iit) {
1024 os << "\\index " << to_utf8(iit->index())
1025 << "\n\\shortcut " << to_utf8(iit->shortcut())
1026 << "\n\\color " << lyx::X11hexname(iit->color())
1031 if (!paperwidth.empty())
1032 os << "\\paperwidth "
1033 << VSpace(paperwidth).asLyXCommand() << '\n';
1034 if (!paperheight.empty())
1035 os << "\\paperheight "
1036 << VSpace(paperheight).asLyXCommand() << '\n';
1037 if (!leftmargin.empty())
1038 os << "\\leftmargin "
1039 << VSpace(leftmargin).asLyXCommand() << '\n';
1040 if (!topmargin.empty())
1041 os << "\\topmargin "
1042 << VSpace(topmargin).asLyXCommand() << '\n';
1043 if (!rightmargin.empty())
1044 os << "\\rightmargin "
1045 << VSpace(rightmargin).asLyXCommand() << '\n';
1046 if (!bottommargin.empty())
1047 os << "\\bottommargin "
1048 << VSpace(bottommargin).asLyXCommand() << '\n';
1049 if (!headheight.empty())
1050 os << "\\headheight "
1051 << VSpace(headheight).asLyXCommand() << '\n';
1052 if (!headsep.empty())
1054 << VSpace(headsep).asLyXCommand() << '\n';
1055 if (!footskip.empty())
1057 << VSpace(footskip).asLyXCommand() << '\n';
1058 if (!columnsep.empty())
1059 os << "\\columnsep "
1060 << VSpace(columnsep).asLyXCommand() << '\n';
1061 os << "\\secnumdepth " << secnumdepth
1062 << "\n\\tocdepth " << tocdepth
1063 << "\n\\paragraph_separation "
1064 << string_paragraph_separation[paragraph_separation];
1065 if (!paragraph_separation)
1066 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1068 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1069 os << "\n\\quotes_language "
1070 << string_quotes_language[quotes_language]
1071 << "\n\\papercolumns " << columns
1072 << "\n\\papersides " << sides
1073 << "\n\\paperpagestyle " << pagestyle << '\n';
1074 if (!listings_params.empty())
1075 os << "\\listings_params \"" <<
1076 InsetListingsParams(listings_params).encodedString() << "\"\n";
1077 for (int i = 0; i < 4; ++i) {
1078 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1079 if (user_defined_bullet(i).getFont() != -1) {
1080 os << "\\bullet " << i << " "
1081 << user_defined_bullet(i).getFont() << " "
1082 << user_defined_bullet(i).getCharacter() << " "
1083 << user_defined_bullet(i).getSize() << "\n";
1087 os << "\\bulletLaTeX " << i << " \""
1088 << lyx::to_ascii(user_defined_bullet(i).getText())
1094 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1095 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1096 << "\\html_math_output " << html_math_output << '\n'
1097 << "\\html_css_as_file " << html_css_as_file << '\n'
1098 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1100 if (html_math_img_scale != 1.0)
1101 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1102 if (!html_latex_start.empty())
1103 os << "\\html_latex_start " << html_latex_start << '\n';
1104 if (!html_latex_end.empty())
1105 os << "\\html_latex_end " << html_latex_end << '\n';
1107 os << pimpl_->authorlist;
1111 void BufferParams::validate(LaTeXFeatures & features) const
1113 features.require(documentClass().requires());
1115 if (outputChanges) {
1116 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1117 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1118 LaTeXFeatures::isAvailable("xcolor");
1120 switch (features.runparams().flavor) {
1121 case OutputParams::LATEX:
1123 features.require("ct-dvipost");
1124 features.require("dvipost");
1125 } else if (xcolorulem) {
1126 features.require("ct-xcolor-ulem");
1127 features.require("ulem");
1128 features.require("xcolor");
1130 features.require("ct-none");
1133 case OutputParams::LUATEX:
1134 case OutputParams::PDFLATEX:
1135 case OutputParams::XETEX:
1137 features.require("ct-xcolor-ulem");
1138 features.require("ulem");
1139 features.require("xcolor");
1140 // improves color handling in PDF output
1141 features.require("pdfcolmk");
1143 features.require("ct-none");
1151 // Floats with 'Here definitely' as default setting.
1152 if (float_placement.find('H') != string::npos)
1153 features.require("float");
1155 // AMS Style is at document level
1156 if (use_amsmath == package_on
1157 || documentClass().provides("amsmath"))
1158 features.require("amsmath");
1159 if (use_esint == package_on)
1160 features.require("esint");
1161 if (use_mhchem == package_on)
1162 features.require("mhchem");
1163 if (use_mathdots == package_on)
1164 features.require("mathdots");
1166 // Document-level line spacing
1167 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1168 features.require("setspace");
1170 // the bullet shapes are buffer level not paragraph level
1171 // so they are tested here
1172 for (int i = 0; i < 4; ++i) {
1173 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1175 int const font = user_defined_bullet(i).getFont();
1177 int const c = user_defined_bullet(i).getCharacter();
1183 features.require("latexsym");
1185 } else if (font == 1) {
1186 features.require("amssymb");
1187 } else if (font >= 2 && font <= 5) {
1188 features.require("pifont");
1192 if (pdfoptions().use_hyperref) {
1193 features.require("hyperref");
1194 // due to interferences with babel and hyperref, the color package has to
1195 // be loaded after hyperref when hyperref is used with the colorlinks
1196 // option, see http://www.lyx.org/trac/ticket/5291
1197 if (pdfoptions().colorlinks)
1198 features.require("color");
1201 if (features.runparams().flavor == OutputParams::XETEX
1203 features.require("polyglossia");
1205 if (language->lang() == "vietnamese")
1206 features.require("vietnamese");
1207 else if (language->lang() == "japanese")
1208 features.require("japanese");
1212 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1213 FileName const & filepath) const
1215 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1216 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1217 // \RequirePackage to do so, rather than the normal \usepackage
1218 // Do not to load any other package before the document class, unless you
1219 // have a thorough understanding of the LATEX internals and know exactly what you
1221 if (features.mustProvide("fix-cm"))
1222 os << "\\RequirePackage{fix-cm}\n";
1224 os << "\\documentclass";
1226 DocumentClass const & tclass = documentClass();
1228 ostringstream clsoptions; // the document class options.
1230 if (tokenPos(tclass.opt_fontsize(),
1231 '|', fontsize) >= 0) {
1232 // only write if existing in list (and not default)
1233 clsoptions << fontsize << "pt,";
1236 // all paper sizes except of A4, A5, B5 and the US sizes need the
1238 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1239 && papersize != PAPER_USLETTER
1240 && papersize != PAPER_USLEGAL
1241 && papersize != PAPER_USEXECUTIVE
1242 && papersize != PAPER_A4
1243 && papersize != PAPER_A5
1244 && papersize != PAPER_B5;
1246 if (!use_geometry) {
1247 switch (papersize) {
1249 clsoptions << "a4paper,";
1251 case PAPER_USLETTER:
1252 clsoptions << "letterpaper,";
1255 clsoptions << "a5paper,";
1258 clsoptions << "b5paper,";
1260 case PAPER_USEXECUTIVE:
1261 clsoptions << "executivepaper,";
1264 clsoptions << "legalpaper,";
1298 if (sides != tclass.sides()) {
1301 clsoptions << "oneside,";
1304 clsoptions << "twoside,";
1310 if (columns != tclass.columns()) {
1312 clsoptions << "twocolumn,";
1314 clsoptions << "onecolumn,";
1318 && orientation == ORIENTATION_LANDSCAPE)
1319 clsoptions << "landscape,";
1321 // language should be a parameter to \documentclass
1322 if (language->babel() == "hebrew"
1323 && default_language->babel() != "hebrew")
1324 // This seems necessary
1325 features.useLanguage(default_language);
1327 ostringstream language_options;
1328 bool const use_babel = features.useBabel() && !tclass.provides("babel");
1329 bool const use_polyglossia = features.usePolyglossia();
1330 bool const global = lyxrc.language_global_options;
1331 if (use_babel || (use_polyglossia && global)) {
1332 language_options << features.getLanguages();
1333 if (!language->babel().empty()) {
1334 if (!language_options.str().empty())
1335 language_options << ',';
1336 language_options << language->babel();
1338 if (global && !features.needBabelLangOptions())
1339 clsoptions << language_options.str() << ',';
1342 // the predefined options from the layout
1343 if (use_default_options && !tclass.options().empty())
1344 clsoptions << tclass.options() << ',';
1346 // the user-defined options
1347 if (!options.empty()) {
1348 clsoptions << options << ',';
1351 string strOptions(clsoptions.str());
1352 if (!strOptions.empty()) {
1353 strOptions = rtrim(strOptions, ",");
1355 os << '[' << from_utf8(strOptions) << ']';
1358 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1359 // end of \documentclass defs
1361 // if we use fontspec, we have to load the AMS packages here
1362 string const ams = features.loadAMSPackages();
1363 if (useNonTeXFonts && !ams.empty())
1364 os << from_ascii(ams);
1367 os << "\\usepackage{fontspec}\n";
1369 // font selection must be done before loading fontenc.sty
1370 string const fonts =
1371 loadFonts(fonts_roman, fonts_sans, fonts_typewriter,
1372 fonts_expert_sc, fonts_old_figures,
1373 fonts_sans_scale, fonts_typewriter_scale,
1374 useNonTeXFonts, features);
1376 os << from_utf8(fonts);
1378 if (fonts_default_family != "default")
1379 os << "\\renewcommand{\\familydefault}{\\"
1380 << from_ascii(fonts_default_family) << "}\n";
1382 // set font encoding
1383 // for arabic_arabi and farsi we also need to load the LAE and
1385 // XeTeX and LuaTeX (with OS fonts) work without fontenc
1386 if (font_encoding() != "default" && language->lang() != "japanese"
1387 && !useNonTeXFonts && !tclass.provides("fontenc")) {
1388 size_t fars = language_options.str().find("farsi");
1389 size_t arab = language_options.str().find("arabic");
1390 if (language->lang() == "arabic_arabi"
1391 || language->lang() == "farsi" || fars != string::npos
1392 || arab != string::npos) {
1393 os << "\\usepackage[" << from_ascii(font_encoding())
1394 << ",LFE,LAE]{fontenc}\n";
1396 os << "\\usepackage[" << from_ascii(font_encoding())
1401 // handle inputenc etc.
1402 writeEncodingPreamble(os, features);
1405 if (!features.runparams().includeall && !included_children_.empty()) {
1406 os << "\\includeonly{";
1407 list<string>::const_iterator it = included_children_.begin();
1408 list<string>::const_iterator en = included_children_.end();
1410 for (; it != en; ++it) {
1411 string incfile = *it;
1412 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1413 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1415 if (!features.runparams().nice)
1417 // \includeonly doesn't want an extension
1418 incfile = changeExtension(incfile, string());
1419 incfile = support::latex_path(incfile);
1420 if (!incfile.empty()) {
1423 os << from_utf8(incfile);
1430 if (!listings_params.empty() || features.isRequired("listings"))
1431 os << "\\usepackage{listings}\n";
1433 if (!listings_params.empty()) {
1435 // do not test validity because listings_params is
1436 // supposed to be valid
1438 InsetListingsParams(listings_params).separatedParams(true);
1439 // we can't support all packages, but we should load the color package
1440 if (par.find("\\color", 0) != string::npos)
1441 features.require("color");
1442 os << from_utf8(par)
1445 if (!tclass.provides("geometry")
1446 && (use_geometry || nonstandard_papersize)) {
1447 odocstringstream ods;
1448 if (!getGraphicsDriver("geometry").empty())
1449 ods << getGraphicsDriver("geometry");
1450 if (orientation == ORIENTATION_LANDSCAPE)
1451 ods << ",landscape";
1452 switch (papersize) {
1454 if (!paperwidth.empty())
1455 ods << ",paperwidth="
1456 << from_ascii(paperwidth);
1457 if (!paperheight.empty())
1458 ods << ",paperheight="
1459 << from_ascii(paperheight);
1461 case PAPER_USLETTER:
1462 ods << ",letterpaper";
1465 ods << ",legalpaper";
1467 case PAPER_USEXECUTIVE:
1468 ods << ",executivepaper";
1555 // default papersize ie PAPER_DEFAULT
1556 switch (lyxrc.default_papersize) {
1557 case PAPER_DEFAULT: // keep compiler happy
1559 case PAPER_USLETTER:
1560 ods << ",letterpaper";
1563 ods << ",legalpaper";
1565 case PAPER_USEXECUTIVE:
1566 ods << ",executivepaper";
1608 docstring const g_options = trim(ods.str(), ",");
1609 os << "\\usepackage";
1610 if (!g_options.empty())
1611 os << '[' << g_options << ']';
1612 os << "{geometry}\n";
1613 // output this only if use_geometry is true
1615 os << "\\geometry{verbose";
1616 if (!topmargin.empty())
1617 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1618 if (!bottommargin.empty())
1619 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1620 if (!leftmargin.empty())
1621 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1622 if (!rightmargin.empty())
1623 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1624 if (!headheight.empty())
1625 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1626 if (!headsep.empty())
1627 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1628 if (!footskip.empty())
1629 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1630 if (!columnsep.empty())
1631 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1634 } else if (orientation == ORIENTATION_LANDSCAPE
1635 || papersize != PAPER_DEFAULT) {
1636 features.require("papersize");
1639 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1640 if (pagestyle == "fancy")
1641 os << "\\usepackage{fancyhdr}\n";
1642 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1645 // only output when the background color is not default
1646 if (isbackgroundcolor == true) {
1647 // only require color here, the background color will be defined
1648 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1650 features.require("color");
1651 features.require("pagecolor");
1654 // only output when the font color is not default
1655 if (isfontcolor == true) {
1656 // only require color here, the font color will be defined
1657 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1659 features.require("color");
1660 features.require("fontcolor");
1663 // Only if class has a ToC hierarchy
1664 if (tclass.hasTocLevels()) {
1665 if (secnumdepth != tclass.secnumdepth()) {
1666 os << "\\setcounter{secnumdepth}{"
1670 if (tocdepth != tclass.tocdepth()) {
1671 os << "\\setcounter{tocdepth}{"
1677 if (paragraph_separation) {
1678 // when skip separation
1679 switch (getDefSkip().kind()) {
1680 case VSpace::SMALLSKIP:
1681 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1683 case VSpace::MEDSKIP:
1684 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1686 case VSpace::BIGSKIP:
1687 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1689 case VSpace::LENGTH:
1690 os << "\\setlength{\\parskip}{"
1691 << from_utf8(getDefSkip().length().asLatexString())
1694 default: // should never happen // Then delete it.
1695 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1698 os << "\\setlength{\\parindent}{0pt}\n";
1700 // when separation by indentation
1701 // only output something when a width is given
1702 if (getIndentation().asLyXCommand() != "default") {
1703 os << "\\setlength{\\parindent}{"
1704 << from_utf8(getIndentation().asLatexCommand())
1709 // Now insert the LyX specific LaTeX commands...
1710 docstring lyxpreamble;
1713 if (!output_sync_macro.empty())
1714 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1715 else if (features.runparams().flavor == OutputParams::LATEX)
1716 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1717 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1718 lyxpreamble += "\\synctex=-1\n";
1721 // due to interferences with babel and hyperref, the color package has to
1722 // be loaded (when it is not already loaded) before babel when hyperref
1723 // is used with the colorlinks option, see
1724 // http://www.lyx.org/trac/ticket/5291
1725 // we decided therefore to load color always before babel, see
1726 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1727 lyxpreamble += from_ascii(features.getColorOptions());
1729 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1731 && (features.isRequired("jurabib")
1732 || features.isRequired("hyperref")
1733 || features.isRequired("vietnamese")
1734 || features.isRequired("japanese"))) {
1736 lyxpreamble += from_utf8(features.getBabelPresettings());
1737 lyxpreamble += from_utf8(babelCall(language_options.str(),
1738 features.needBabelLangOptions())) + '\n';
1739 lyxpreamble += from_utf8(features.getBabelPostsettings());
1742 // The optional packages;
1743 lyxpreamble += from_ascii(features.getPackages());
1745 // Additional Indices
1746 if (features.isRequired("splitidx")) {
1747 IndicesList::const_iterator iit = indiceslist().begin();
1748 IndicesList::const_iterator iend = indiceslist().end();
1749 for (; iit != iend; ++iit) {
1750 lyxpreamble += "\\newindex[";
1751 lyxpreamble += iit->index();
1752 lyxpreamble += "]{";
1753 lyxpreamble += iit->shortcut();
1754 lyxpreamble += "}\n";
1759 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1762 // * Hyperref manual: "Make sure it comes last of your loaded
1763 // packages, to give it a fighting chance of not being over-written,
1764 // since its job is to redefine many LaTeX commands."
1765 // * Email from Heiko Oberdiek: "It is usually better to load babel
1766 // before hyperref. Then hyperref has a chance to detect babel.
1767 // * Has to be loaded before the "LyX specific LaTeX commands" to
1768 // avoid errors with algorithm floats.
1769 // use hyperref explicitly if it is required
1770 if (features.isRequired("hyperref")) {
1771 // pass what we have to stream here, since we need
1772 // to access the stream itself in PDFOptions.
1775 OutputParams tmp_params = features.runparams();
1776 pdfoptions().writeLaTeX(tmp_params, os,
1777 documentClass().provides("hyperref"));
1778 // set back for the rest
1779 lyxpreamble.clear();
1780 // correctly break URLs with hyperref and dvi output
1781 if (features.runparams().flavor == OutputParams::LATEX
1782 && features.isAvailable("breakurl"))
1783 lyxpreamble += "\\usepackage{breakurl}\n";
1784 } else if (features.isRequired("nameref"))
1785 // hyperref loads this automatically
1786 lyxpreamble += "\\usepackage{nameref}\n";
1788 // Will be surrounded by \makeatletter and \makeatother when not empty
1789 docstring atlyxpreamble;
1791 // Some macros LyX will need
1792 docstring tmppreamble(features.getMacros());
1794 if (!tmppreamble.empty())
1795 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1796 "LyX specific LaTeX commands.\n"
1797 + tmppreamble + '\n';
1799 // the text class specific preamble
1800 tmppreamble = features.getTClassPreamble();
1801 if (!tmppreamble.empty())
1802 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1803 "Textclass specific LaTeX commands.\n"
1804 + tmppreamble + '\n';
1806 // suppress date if selected
1807 // use \@ifundefined because we cannot be sure that every document class
1808 // has a \date command
1810 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1812 /* the user-defined preamble */
1813 if (!containsOnly(preamble, " \n\t"))
1815 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1816 "User specified LaTeX commands.\n"
1817 + from_utf8(preamble) + '\n';
1819 // subfig loads internally the LaTeX package "caption". As
1820 // caption is a very popular package, users will load it in
1821 // the preamble. Therefore we must load subfig behind the
1822 // user-defined preamble and check if the caption package was
1823 // loaded or not. For the case that caption is loaded before
1824 // subfig, there is the subfig option "caption=false". This
1825 // option also works when a koma-script class is used and
1826 // koma's own caption commands are used instead of caption. We
1827 // use \PassOptionsToPackage here because the user could have
1828 // already loaded subfig in the preamble.
1829 if (features.isRequired("subfig")) {
1830 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1831 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1832 "\\usepackage{subfig}\n";
1835 // Itemize bullet settings need to be last in case the user
1836 // defines their own bullets that use a package included
1837 // in the user-defined preamble -- ARRae
1838 // Actually it has to be done much later than that
1839 // since some packages like frenchb make modifications
1840 // at \begin{document} time -- JMarc
1841 docstring bullets_def;
1842 for (int i = 0; i < 4; ++i) {
1843 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1844 if (bullets_def.empty())
1845 bullets_def += "\\AtBeginDocument{\n";
1846 bullets_def += " \\def\\labelitemi";
1848 // `i' is one less than the item to modify
1855 bullets_def += "ii";
1861 bullets_def += '{' +
1862 user_defined_bullet(i).getText()
1867 if (!bullets_def.empty())
1868 atlyxpreamble += bullets_def + "}\n\n";
1870 if (!atlyxpreamble.empty())
1871 lyxpreamble += "\n\\makeatletter\n"
1872 + atlyxpreamble + "\\makeatother\n\n";
1874 // We try to load babel late, in case it interferes with other packages.
1875 // Jurabib and Hyperref have to be called after babel, though.
1876 if (use_babel && !features.isRequired("jurabib")
1877 && !features.isRequired("hyperref")
1878 && !features.isRequired("vietnamese")
1879 && !features.isRequired("japanese")) {
1881 lyxpreamble += from_utf8(features.getBabelPresettings());
1882 lyxpreamble += from_utf8(babelCall(language_options.str(),
1883 features.needBabelLangOptions())) + '\n';
1884 lyxpreamble += from_utf8(features.getBabelPostsettings());
1887 // xunicode needs to be loaded at least after amsmath, amssymb,
1888 // esint and the other packages that provide special glyphs
1889 if (features.runparams().flavor == OutputParams::XETEX)
1890 lyxpreamble += "\\usepackage{xunicode}\n";
1892 // Polyglossia must be loaded last
1893 if (use_polyglossia) {
1895 lyxpreamble += "\\usepackage{polyglossia}\n";
1896 // set the main language
1897 lyxpreamble += "\\setdefaultlanguage";
1898 if (!language->polyglossiaOpts().empty())
1899 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1900 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1901 // now setup the other languages
1902 std::map<std::string, std::string> const polylangs =
1903 features.getPolyglossiaLanguages();
1904 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1905 mit != polylangs.end() ; ++mit) {
1906 lyxpreamble += "\\setotherlanguage";
1907 if (!mit->second.empty())
1908 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1909 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
1913 docstring const i18npreamble =
1914 features.getTClassI18nPreamble(use_babel, use_polyglossia);
1915 if (!i18npreamble.empty())
1916 lyxpreamble += i18npreamble + '\n';
1924 void BufferParams::useClassDefaults()
1926 DocumentClass const & tclass = documentClass();
1928 sides = tclass.sides();
1929 columns = tclass.columns();
1930 pagestyle = tclass.pagestyle();
1931 use_default_options = true;
1932 // Only if class has a ToC hierarchy
1933 if (tclass.hasTocLevels()) {
1934 secnumdepth = tclass.secnumdepth();
1935 tocdepth = tclass.tocdepth();
1940 bool BufferParams::hasClassDefaults() const
1942 DocumentClass const & tclass = documentClass();
1944 return sides == tclass.sides()
1945 && columns == tclass.columns()
1946 && pagestyle == tclass.pagestyle()
1947 && use_default_options
1948 && secnumdepth == tclass.secnumdepth()
1949 && tocdepth == tclass.tocdepth();
1953 DocumentClass const & BufferParams::documentClass() const
1959 DocumentClass const * BufferParams::documentClassPtr() const
1965 void BufferParams::setDocumentClass(DocumentClass const * const tc)
1967 // evil, but this function is evil
1968 doc_class_ = const_cast<DocumentClass *>(tc);
1972 bool BufferParams::setBaseClass(string const & classname)
1974 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1975 LayoutFileList & bcl = LayoutFileList::get();
1976 if (!bcl.haveClass(classname)) {
1978 bformat(_("The layout file:\n"
1980 "could not be found. A default textclass with default\n"
1981 "layouts will be used. LyX will not be able to produce\n"
1983 from_utf8(classname));
1984 frontend::Alert::error(_("Document class not found"), s);
1985 bcl.addEmptyClass(classname);
1988 bool const success = bcl[classname].load();
1991 bformat(_("Due to some error in it, the layout file:\n"
1993 "could not be loaded. A default textclass with default\n"
1994 "layouts will be used. LyX will not be able to produce\n"
1996 from_utf8(classname));
1997 frontend::Alert::error(_("Could not load class"), s);
1998 bcl.addEmptyClass(classname);
2001 pimpl_->baseClass_ = classname;
2002 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2007 LayoutFile const * BufferParams::baseClass() const
2009 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2010 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2016 LayoutFileIndex const & BufferParams::baseClassID() const
2018 return pimpl_->baseClass_;
2022 void BufferParams::makeDocumentClass()
2027 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layout_modules_));
2029 if (!local_layout.empty()) {
2030 TextClass::ReturnValues success =
2031 doc_class_->read(local_layout, TextClass::MODULE);
2032 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2033 docstring const msg = _("Error reading internal layout information");
2034 frontend::Alert::warning(_("Read Error"), msg);
2040 bool BufferParams::moduleCanBeAdded(string const & modName) const
2042 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2046 bool BufferParams::addLayoutModule(string const & modName)
2048 LayoutModuleList::const_iterator it = layout_modules_.begin();
2049 LayoutModuleList::const_iterator end = layout_modules_.end();
2050 for (; it != end; it++)
2053 layout_modules_.push_back(modName);
2058 string BufferParams::bufferFormat() const
2060 string format = documentClass().outputFormat();
2061 if (format == "latex") {
2064 if (encoding().package() == Encoding::japanese)
2071 bool BufferParams::isExportable(string const & format) const
2073 vector<string> backs = backends();
2074 for (vector<string>::const_iterator it = backs.begin();
2075 it != backs.end(); ++it)
2076 if (theConverters().isReachable(*it, format))
2082 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2084 vector<string> const backs = backends();
2085 set<string> excludes;
2086 if (useNonTeXFonts) {
2087 excludes.insert("latex");
2088 excludes.insert("pdflatex");
2090 vector<Format const *> result =
2091 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2092 for (vector<string>::const_iterator it = backs.begin() + 1;
2093 it != backs.end(); ++it) {
2094 vector<Format const *> r =
2095 theConverters().getReachable(*it, only_viewable, false, excludes);
2096 result.insert(result.end(), r.begin(), r.end());
2102 bool BufferParams::isExportableFormat(string const & format) const
2104 typedef vector<Format const *> Formats;
2106 formats = exportableFormats(true);
2107 Formats::const_iterator fit = formats.begin();
2108 Formats::const_iterator end = formats.end();
2109 for (; fit != end ; ++fit) {
2110 if ((*fit)->name() == format)
2117 vector<string> BufferParams::backends() const
2120 v.push_back(bufferFormat());
2121 // FIXME: Don't hardcode format names here, but use a flag
2122 if (v.back() == "latex") {
2123 v.push_back("pdflatex");
2124 v.push_back("luatex");
2125 v.push_back("xetex");
2126 } else if (v.back() == "xetex")
2127 v.push_back("luatex");
2128 v.push_back("xhtml");
2129 v.push_back("text");
2135 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const format) const
2137 string const dformat = (format.empty() || format == "default") ?
2138 getDefaultOutputFormat() : format;
2139 DefaultFlavorCache::const_iterator it =
2140 default_flavors_.find(dformat);
2142 if (it != default_flavors_.end())
2145 OutputParams::FLAVOR result = OutputParams::LATEX;
2147 if (dformat == "xhtml")
2148 result = OutputParams::HTML;
2150 // Try to determine flavor of default output format
2151 vector<string> backs = backends();
2152 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2153 // Get shortest path to format
2154 Graph::EdgePath path;
2155 for (vector<string>::const_iterator it = backs.begin();
2156 it != backs.end(); ++it) {
2157 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2158 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2163 result = theConverters().getFlavor(path);
2166 // cache this flavor
2167 default_flavors_[dformat] = result;
2172 string BufferParams::getDefaultOutputFormat() const
2174 if (!default_output_format.empty()
2175 && default_output_format != "default")
2176 return default_output_format;
2179 || encoding().package() == Encoding::japanese) {
2180 vector<Format const *> const formats = exportableFormats(true);
2181 if (formats.empty())
2183 // return the first we find
2184 return formats.front()->name();
2186 return lyxrc.default_view_format;
2189 Font const BufferParams::getFont() const
2191 FontInfo f = documentClass().defaultfont();
2192 if (fonts_default_family == "rmdefault")
2193 f.setFamily(ROMAN_FAMILY);
2194 else if (fonts_default_family == "sfdefault")
2195 f.setFamily(SANS_FAMILY);
2196 else if (fonts_default_family == "ttdefault")
2197 f.setFamily(TYPEWRITER_FAMILY);
2198 return Font(f, language);
2202 bool BufferParams::isLatex() const
2204 return documentClass().outputType() == LATEX;
2208 bool BufferParams::isLiterate() const
2210 return documentClass().outputType() == LITERATE;
2214 bool BufferParams::isDocBook() const
2216 return documentClass().outputType() == DOCBOOK;
2220 void BufferParams::readPreamble(Lexer & lex)
2222 if (lex.getString() != "\\begin_preamble")
2223 lyxerr << "Error (BufferParams::readPreamble):"
2224 "consistency check failed." << endl;
2226 preamble = lex.getLongString("\\end_preamble");
2230 void BufferParams::readLocalLayout(Lexer & lex)
2232 if (lex.getString() != "\\begin_local_layout")
2233 lyxerr << "Error (BufferParams::readLocalLayout):"
2234 "consistency check failed." << endl;
2236 local_layout = lex.getLongString("\\end_local_layout");
2240 bool BufferParams::setLanguage(string const & lang)
2242 Language const *new_language = languages.getLanguage(lang);
2243 if (!new_language) {
2244 // Language lang was not found
2247 language = new_language;
2252 void BufferParams::readLanguage(Lexer & lex)
2254 if (!lex.next()) return;
2256 string const tmptok = lex.getString();
2258 // check if tmptok is part of tex_babel in tex-defs.h
2259 if (!setLanguage(tmptok)) {
2260 // Language tmptok was not found
2261 language = default_language;
2262 lyxerr << "Warning: Setting language `"
2263 << tmptok << "' to `" << language->lang()
2269 void BufferParams::readGraphicsDriver(Lexer & lex)
2274 string const tmptok = lex.getString();
2275 // check if tmptok is part of tex_graphics in tex_defs.h
2278 string const test = tex_graphics[n++];
2280 if (test == tmptok) {
2281 graphics_driver = tmptok;
2286 "Warning: graphics driver `$$Token' not recognized!\n"
2287 " Setting graphics driver to `default'.\n");
2288 graphics_driver = "default";
2295 void BufferParams::readBullets(Lexer & lex)
2300 int const index = lex.getInteger();
2302 int temp_int = lex.getInteger();
2303 user_defined_bullet(index).setFont(temp_int);
2304 temp_bullet(index).setFont(temp_int);
2306 user_defined_bullet(index).setCharacter(temp_int);
2307 temp_bullet(index).setCharacter(temp_int);
2309 user_defined_bullet(index).setSize(temp_int);
2310 temp_bullet(index).setSize(temp_int);
2314 void BufferParams::readBulletsLaTeX(Lexer & lex)
2316 // The bullet class should be able to read this.
2319 int const index = lex.getInteger();
2321 docstring const temp_str = lex.getDocString();
2323 user_defined_bullet(index).setText(temp_str);
2324 temp_bullet(index).setText(temp_str);
2328 void BufferParams::readModules(Lexer & lex)
2330 if (!lex.eatLine()) {
2331 lyxerr << "Error (BufferParams::readModules):"
2332 "Unexpected end of input." << endl;
2336 string mod = lex.getString();
2337 if (mod == "\\end_modules")
2339 addLayoutModule(mod);
2345 void BufferParams::readRemovedModules(Lexer & lex)
2347 if (!lex.eatLine()) {
2348 lyxerr << "Error (BufferParams::readRemovedModules):"
2349 "Unexpected end of input." << endl;
2353 string mod = lex.getString();
2354 if (mod == "\\end_removed_modules")
2356 removed_modules_.push_back(mod);
2359 // now we want to remove any removed modules that were previously
2360 // added. normally, that will be because default modules were added in
2361 // setBaseClass(), which gets called when \textclass is read at the
2362 // start of the read.
2363 list<string>::const_iterator rit = removed_modules_.begin();
2364 list<string>::const_iterator const ren = removed_modules_.end();
2365 for (; rit != ren; rit++) {
2366 LayoutModuleList::iterator const mit = layout_modules_.begin();
2367 LayoutModuleList::iterator const men = layout_modules_.end();
2368 LayoutModuleList::iterator found = find(mit, men, *rit);
2371 layout_modules_.erase(found);
2376 void BufferParams::readIncludeonly(Lexer & lex)
2378 if (!lex.eatLine()) {
2379 lyxerr << "Error (BufferParams::readIncludeonly):"
2380 "Unexpected end of input." << endl;
2384 string child = lex.getString();
2385 if (child == "\\end_includeonly")
2387 included_children_.push_back(child);
2393 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2395 char real_papersize = papersize;
2396 if (real_papersize == PAPER_DEFAULT)
2397 real_papersize = lyxrc.default_papersize;
2399 switch (real_papersize) {
2401 // could be anything, so don't guess
2403 case PAPER_CUSTOM: {
2404 if (purpose == XDVI && !paperwidth.empty() &&
2405 !paperheight.empty()) {
2406 // heightxwidth<unit>
2407 string first = paperwidth;
2408 string second = paperheight;
2409 if (orientation == ORIENTATION_LANDSCAPE)
2412 return first.erase(first.length() - 2)
2418 // dvips and dvipdfm do not know this
2419 if (purpose == DVIPS || purpose == DVIPDFM)
2423 if (purpose == DVIPS || purpose == DVIPDFM)
2427 if (purpose == DVIPS || purpose == DVIPDFM)
2437 if (purpose == DVIPS || purpose == DVIPDFM)
2441 if (purpose == DVIPS || purpose == DVIPDFM)
2445 if (purpose == DVIPS || purpose == DVIPDFM)
2449 if (purpose == DVIPS || purpose == DVIPDFM)
2453 if (purpose == DVIPS || purpose == DVIPDFM)
2457 // dvipdfm does not know this
2458 if (purpose == DVIPDFM)
2462 if (purpose == DVIPDFM)
2466 if (purpose == DVIPS || purpose == DVIPDFM)
2470 if (purpose == DVIPS || purpose == DVIPDFM)
2474 if (purpose == DVIPS || purpose == DVIPDFM)
2478 if (purpose == DVIPS || purpose == DVIPDFM)
2482 if (purpose == DVIPS || purpose == DVIPDFM)
2486 if (purpose == DVIPS || purpose == DVIPDFM)
2490 if (purpose == DVIPS || purpose == DVIPDFM)
2494 if (purpose == DVIPS || purpose == DVIPDFM)
2498 if (purpose == DVIPS || purpose == DVIPDFM)
2502 if (purpose == DVIPS || purpose == DVIPDFM)
2506 if (purpose == DVIPS || purpose == DVIPDFM)
2510 if (purpose == DVIPS || purpose == DVIPDFM)
2514 if (purpose == DVIPS || purpose == DVIPDFM)
2518 if (purpose == DVIPS || purpose == DVIPDFM)
2522 if (purpose == DVIPS || purpose == DVIPDFM)
2525 case PAPER_USEXECUTIVE:
2526 // dvipdfm does not know this
2527 if (purpose == DVIPDFM)
2532 case PAPER_USLETTER:
2534 if (purpose == XDVI)
2541 string const BufferParams::dvips_options() const
2546 && papersize == PAPER_CUSTOM
2547 && !lyxrc.print_paper_dimension_flag.empty()
2548 && !paperwidth.empty()
2549 && !paperheight.empty()) {
2550 // using a custom papersize
2551 result = lyxrc.print_paper_dimension_flag;
2552 result += ' ' + paperwidth;
2553 result += ',' + paperheight;
2555 string const paper_option = paperSizeName(DVIPS);
2556 if (!paper_option.empty() && (paper_option != "letter" ||
2557 orientation != ORIENTATION_LANDSCAPE)) {
2558 // dvips won't accept -t letter -t landscape.
2559 // In all other cases, include the paper size
2561 result = lyxrc.print_paper_flag;
2562 result += ' ' + paper_option;
2565 if (orientation == ORIENTATION_LANDSCAPE &&
2566 papersize != PAPER_CUSTOM)
2567 result += ' ' + lyxrc.print_landscape_flag;
2572 string const BufferParams::font_encoding() const
2574 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2578 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2580 if (lang_package != "auto" && lang_package != "babel"
2581 && lang_package != "default" && lang_package != "none")
2582 return lang_package;
2583 if (lyxrc.language_package_selection == LyXRC::LP_CUSTOM)
2584 return lyxrc.language_custom_package;
2585 // suppress the babel call if there is no BabelName defined
2586 // for the document language in the lib/languages file and if no
2587 // other languages are used (lang_opts is then empty)
2588 if (lang_opts.empty())
2590 // either a specific language (AsBabelOptions setting in
2591 // lib/languages) or the prefs require the languages to
2592 // be submitted to babel itself (not the class).
2594 return "\\usepackage[" + lang_opts + "]{babel}";
2595 return "\\usepackage{babel}";
2599 docstring BufferParams::getGraphicsDriver(string const & package) const
2603 if (package == "geometry") {
2604 if (graphics_driver == "dvips"
2605 || graphics_driver == "dvipdfm"
2606 || graphics_driver == "pdftex"
2607 || graphics_driver == "vtex")
2608 result = from_ascii(graphics_driver);
2609 else if (graphics_driver == "dvipdfmx")
2610 result = from_ascii("dvipdfm");
2617 void BufferParams::writeEncodingPreamble(otexstream & os,
2618 LaTeXFeatures & features) const
2620 // XeTeX does not need this
2621 if (features.runparams().flavor == OutputParams::XETEX)
2623 // LuaTeX neither, but with tex fonts, we need to load
2624 // the luainputenc package.
2625 if (features.runparams().flavor == OutputParams::LUATEX) {
2626 if (!useNonTeXFonts && inputenc != "default"
2627 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2628 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2629 os << "\\usepackage[utf8]{luainputenc}\n";
2633 if (inputenc == "auto") {
2634 string const doc_encoding =
2635 language->encoding()->latexName();
2636 Encoding::Package const package =
2637 language->encoding()->package();
2639 // Create a list with all the input encodings used
2641 set<string> encodings =
2642 features.getEncodingSet(doc_encoding);
2644 // If the "japanese" package (i.e. pLaTeX) is used,
2645 // inputenc must be omitted.
2646 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2647 if (package == Encoding::japanese)
2648 features.require("japanese");
2650 if ((!encodings.empty() || package == Encoding::inputenc)
2651 && !features.isRequired("japanese")) {
2652 os << "\\usepackage[";
2653 set<string>::const_iterator it = encodings.begin();
2654 set<string>::const_iterator const end = encodings.end();
2656 os << from_ascii(*it);
2659 for (; it != end; ++it)
2660 os << ',' << from_ascii(*it);
2661 if (package == Encoding::inputenc) {
2662 if (!encodings.empty())
2664 os << from_ascii(doc_encoding);
2666 os << "]{inputenc}\n";
2668 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2669 if (language->encoding()->name() == "utf8-cjk"
2670 && LaTeXFeatures::isAvailable("CJKutf8"))
2671 os << "\\usepackage{CJKutf8}\n";
2673 os << "\\usepackage{CJK}\n";
2675 } else if (inputenc != "default") {
2676 switch (encoding().package()) {
2677 case Encoding::none:
2678 case Encoding::japanese:
2680 case Encoding::inputenc:
2681 // do not load inputenc if japanese is used
2682 if (features.isRequired("japanese"))
2684 os << "\\usepackage[" << from_ascii(inputenc)
2688 if (encoding().name() == "utf8-cjk"
2689 && LaTeXFeatures::isAvailable("CJKutf8"))
2690 os << "\\usepackage{CJKutf8}\n";
2692 os << "\\usepackage{CJK}\n";
2697 // The encoding "armscii8" (for Armenian) is only available when
2698 // the package "armtex" is loaded.
2699 if (language->encoding()->latexName() == "armscii8"
2700 || inputenc == "armscii8")
2701 os << "\\usepackage{armtex}\n";
2705 string const BufferParams::parseFontName(string const & name) const
2707 string mangled = name;
2708 size_t const idx = mangled.find('[');
2709 if (idx == string::npos || idx == 0)
2712 return mangled.substr(0, idx - 1);
2716 string const BufferParams::loadFonts(string const & rm,
2717 string const & sf, string const & tt,
2718 bool const & sc, bool const & osf,
2719 int const & sfscale, int const & ttscale,
2720 bool const & use_systemfonts,
2721 LaTeXFeatures & features) const
2723 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2724 several packages have been replaced by others, that might not
2725 be installed on every system. We have to take care for that
2726 (see psnfss.pdf). We try to support all psnfss fonts as well
2727 as the fonts that have become de facto standard in the LaTeX
2728 world (e.g. Latin Modern). We do not support obsolete fonts
2729 (like PSLatex). In general, it should be possible to mix any
2730 rm font with any sf or tt font, respectively. (JSpitzm)
2732 -- separate math fonts.
2735 if (rm == "default" && sf == "default" && tt == "default")
2741 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2742 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2743 * Mapping=tex-text option assures TeX ligatures (such as "--")
2744 * are resolved. Note that tt does not use these ligatures.
2746 * -- add more GUI options?
2747 * -- add more fonts (fonts for other scripts)
2748 * -- if there's a way to find out if a font really supports
2749 * OldStyle, enable/disable the widget accordingly.
2751 if (use_systemfonts && features.isAvailable("fontspec")) {
2752 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2753 // However, until v.2 (2010/07/11) fontspec only knew
2754 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2755 // was introduced for both XeTeX and LuaTeX (LuaTeX
2756 // didn't understand "Mapping=tex-text", while XeTeX
2757 // understood both. With most recent versions, both
2758 // variants are understood by both engines. However,
2759 // we want to provide support for at least TeXLive 2009
2760 // (for XeTeX; LuaTeX is only supported as of v.2)
2761 string const texmapping =
2762 (features.runparams().flavor == OutputParams::XETEX) ?
2763 "Mapping=tex-text" : "Ligatures=TeX";
2764 if (rm != "default") {
2765 os << "\\setmainfont[" << texmapping;
2767 os << ",Numbers=OldStyle";
2768 os << "]{" << parseFontName(rm) << "}\n";
2770 if (sf != "default") {
2771 string const sans = parseFontName(sf);
2773 os << "\\setsansfont[Scale="
2774 << float(sfscale) / 100
2775 << "," << texmapping << "]{"
2778 os << "\\setsansfont[" << texmapping << "]{"
2781 if (tt != "default") {
2782 string const mono = parseFontName(tt);
2784 os << "\\setmonofont[Scale="
2785 << float(ttscale) / 100
2789 os << "\\setmonofont{"
2796 // Computer Modern (must be explicitly selectable -- there might be classes
2797 // that define a different default font!
2799 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2800 // osf for Computer Modern needs eco.sty
2802 os << "\\usepackage{eco}\n";
2804 // Latin Modern Roman
2805 else if (rm == "lmodern")
2806 os << "\\usepackage{lmodern}\n";
2808 else if (rm == "ae") {
2809 // not needed when using OT1 font encoding.
2810 if (font_encoding() != "default")
2811 os << "\\usepackage{ae,aecompl}\n";
2814 else if (rm == "times") {
2815 // try to load the best available package
2816 if (LaTeXFeatures::isAvailable("mathptmx"))
2817 os << "\\usepackage{mathptmx}\n";
2818 else if (LaTeXFeatures::isAvailable("mathptm"))
2819 os << "\\usepackage{mathptm}\n";
2821 os << "\\usepackage{times}\n";
2824 else if (rm == "palatino") {
2825 // try to load the best available package
2826 if (LaTeXFeatures::isAvailable("mathpazo")) {
2827 os << "\\usepackage";
2833 // "osf" includes "sc"!
2837 os << "{mathpazo}\n";
2839 else if (LaTeXFeatures::isAvailable("mathpple"))
2840 os << "\\usepackage{mathpple}\n";
2842 os << "\\usepackage{palatino}\n";
2845 else if (rm == "utopia") {
2846 // fourier supersedes utopia.sty, but does
2847 // not work with OT1 encoding.
2848 if (LaTeXFeatures::isAvailable("fourier")
2849 && font_encoding() != "default") {
2850 os << "\\usepackage";
2861 os << "{fourier}\n";
2864 os << "\\usepackage{utopia}\n";
2866 // Bera (complete fontset)
2867 else if (rm == "bera" && sf == "default" && tt == "default")
2868 os << "\\usepackage{bera}\n";
2870 else if (rm != "default")
2871 os << "\\usepackage" << "{" << rm << "}\n";
2874 // Helvetica, Bera Sans
2875 if (sf == "helvet" || sf == "berasans") {
2877 os << "\\usepackage[scaled=" << float(sfscale) / 100
2878 << "]{" << sf << "}\n";
2880 os << "\\usepackage{" << sf << "}\n";
2883 else if (sf == "avant")
2884 os << "\\usepackage{" << sf << "}\n";
2885 // Computer Modern, Latin Modern, CM Bright
2886 else if (sf != "default")
2887 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2889 // monospaced/typewriter
2890 // Courier, LuxiMono
2891 if (tt == "luximono" || tt == "beramono") {
2893 os << "\\usepackage[scaled=" << float(ttscale) / 100
2894 << "]{" << tt << "}\n";
2896 os << "\\usepackage{" << tt << "}\n";
2899 else if (tt == "courier" )
2900 os << "\\usepackage{" << tt << "}\n";
2901 // Computer Modern, Latin Modern, CM Bright
2902 else if (tt != "default")
2903 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2909 Encoding const & BufferParams::encoding() const
2911 // FIXME: actually, we should check for the flavor
2912 // or runparams.isFullyUnicode() here:
2913 // This check will not work with XeTeX/LuaTeX and tex fonts.
2914 // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2916 return *(encodings.fromLaTeXName("utf8-plain"));
2917 if (inputenc == "auto" || inputenc == "default")
2918 return *language->encoding();
2919 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2922 LYXERR0("Unknown inputenc value `" << inputenc
2923 << "'. Using `auto' instead.");
2924 return *language->encoding();
2928 CiteEngine BufferParams::citeEngine() const
2930 // FIXME the class should provide the numerical/
2931 // authoryear choice
2932 if (documentClass().provides("natbib")
2933 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2934 return ENGINE_NATBIB_AUTHORYEAR;
2935 return cite_engine_;
2939 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2941 cite_engine_ = cite_engine;