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:
1122 case OutputParams::DVILUATEX:
1124 features.require("ct-dvipost");
1125 features.require("dvipost");
1126 } else if (xcolorulem) {
1127 features.require("ct-xcolor-ulem");
1128 features.require("ulem");
1129 features.require("xcolor");
1131 features.require("ct-none");
1134 case OutputParams::LUATEX:
1135 case OutputParams::PDFLATEX:
1136 case OutputParams::XETEX:
1138 features.require("ct-xcolor-ulem");
1139 features.require("ulem");
1140 features.require("xcolor");
1141 // improves color handling in PDF output
1142 features.require("pdfcolmk");
1144 features.require("ct-none");
1152 // Floats with 'Here definitely' as default setting.
1153 if (float_placement.find('H') != string::npos)
1154 features.require("float");
1156 // AMS Style is at document level
1157 if (use_amsmath == package_on
1158 || documentClass().provides("amsmath"))
1159 features.require("amsmath");
1160 if (use_esint == package_on)
1161 features.require("esint");
1162 if (use_mhchem == package_on)
1163 features.require("mhchem");
1164 if (use_mathdots == package_on)
1165 features.require("mathdots");
1167 // Document-level line spacing
1168 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1169 features.require("setspace");
1171 // the bullet shapes are buffer level not paragraph level
1172 // so they are tested here
1173 for (int i = 0; i < 4; ++i) {
1174 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1176 int const font = user_defined_bullet(i).getFont();
1178 int const c = user_defined_bullet(i).getCharacter();
1184 features.require("latexsym");
1186 } else if (font == 1) {
1187 features.require("amssymb");
1188 } else if (font >= 2 && font <= 5) {
1189 features.require("pifont");
1193 if (pdfoptions().use_hyperref) {
1194 features.require("hyperref");
1195 // due to interferences with babel and hyperref, the color package has to
1196 // be loaded after hyperref when hyperref is used with the colorlinks
1197 // option, see http://www.lyx.org/trac/ticket/5291
1198 if (pdfoptions().colorlinks)
1199 features.require("color");
1202 if (features.runparams().flavor == OutputParams::XETEX
1204 features.require("polyglossia");
1206 if (language->lang() == "vietnamese")
1207 features.require("vietnamese");
1208 else if (language->lang() == "japanese")
1209 features.require("japanese");
1213 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1214 FileName const & filepath) const
1216 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1217 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1218 // \RequirePackage to do so, rather than the normal \usepackage
1219 // Do not to load any other package before the document class, unless you
1220 // have a thorough understanding of the LATEX internals and know exactly what you
1222 if (features.mustProvide("fix-cm"))
1223 os << "\\RequirePackage{fix-cm}\n";
1225 os << "\\documentclass";
1227 DocumentClass const & tclass = documentClass();
1229 ostringstream clsoptions; // the document class options.
1231 if (tokenPos(tclass.opt_fontsize(),
1232 '|', fontsize) >= 0) {
1233 // only write if existing in list (and not default)
1234 clsoptions << fontsize << "pt,";
1237 // all paper sizes except of A4, A5, B5 and the US sizes need the
1239 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1240 && papersize != PAPER_USLETTER
1241 && papersize != PAPER_USLEGAL
1242 && papersize != PAPER_USEXECUTIVE
1243 && papersize != PAPER_A4
1244 && papersize != PAPER_A5
1245 && papersize != PAPER_B5;
1247 if (!use_geometry) {
1248 switch (papersize) {
1250 clsoptions << "a4paper,";
1252 case PAPER_USLETTER:
1253 clsoptions << "letterpaper,";
1256 clsoptions << "a5paper,";
1259 clsoptions << "b5paper,";
1261 case PAPER_USEXECUTIVE:
1262 clsoptions << "executivepaper,";
1265 clsoptions << "legalpaper,";
1299 if (sides != tclass.sides()) {
1302 clsoptions << "oneside,";
1305 clsoptions << "twoside,";
1311 if (columns != tclass.columns()) {
1313 clsoptions << "twocolumn,";
1315 clsoptions << "onecolumn,";
1319 && orientation == ORIENTATION_LANDSCAPE)
1320 clsoptions << "landscape,";
1322 // language should be a parameter to \documentclass
1323 if (language->babel() == "hebrew"
1324 && default_language->babel() != "hebrew")
1325 // This seems necessary
1326 features.useLanguage(default_language);
1328 ostringstream language_options;
1329 bool const use_babel = features.useBabel() && !tclass.provides("babel");
1330 bool const use_polyglossia = features.usePolyglossia();
1331 bool const global = lyxrc.language_global_options;
1332 if (use_babel || (use_polyglossia && global)) {
1333 language_options << features.getLanguages();
1334 if (!language->babel().empty()) {
1335 if (!language_options.str().empty())
1336 language_options << ',';
1337 language_options << language->babel();
1339 if (global && !features.needBabelLangOptions())
1340 clsoptions << language_options.str() << ',';
1343 // the predefined options from the layout
1344 if (use_default_options && !tclass.options().empty())
1345 clsoptions << tclass.options() << ',';
1347 // the user-defined options
1348 if (!options.empty()) {
1349 clsoptions << options << ',';
1352 string strOptions(clsoptions.str());
1353 if (!strOptions.empty()) {
1354 strOptions = rtrim(strOptions, ",");
1356 os << '[' << from_utf8(strOptions) << ']';
1359 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1360 // end of \documentclass defs
1362 // if we use fontspec, we have to load the AMS packages here
1363 string const ams = features.loadAMSPackages();
1364 if (useNonTeXFonts && !ams.empty())
1365 os << from_ascii(ams);
1368 os << "\\usepackage{fontspec}\n";
1370 // font selection must be done before loading fontenc.sty
1371 string const fonts =
1372 loadFonts(fonts_roman, fonts_sans, fonts_typewriter,
1373 fonts_expert_sc, fonts_old_figures,
1374 fonts_sans_scale, fonts_typewriter_scale,
1375 useNonTeXFonts, features);
1377 os << from_utf8(fonts);
1379 if (fonts_default_family != "default")
1380 os << "\\renewcommand{\\familydefault}{\\"
1381 << from_ascii(fonts_default_family) << "}\n";
1383 // set font encoding
1384 // for arabic_arabi and farsi we also need to load the LAE and
1386 // XeTeX and LuaTeX (with OS fonts) work without fontenc
1387 if (font_encoding() != "default" && language->lang() != "japanese"
1388 && !useNonTeXFonts && !tclass.provides("fontenc")) {
1389 size_t fars = language_options.str().find("farsi");
1390 size_t arab = language_options.str().find("arabic");
1391 if (language->lang() == "arabic_arabi"
1392 || language->lang() == "farsi" || fars != string::npos
1393 || arab != string::npos) {
1394 os << "\\usepackage[" << from_ascii(font_encoding())
1395 << ",LFE,LAE]{fontenc}\n";
1397 os << "\\usepackage[" << from_ascii(font_encoding())
1402 // handle inputenc etc.
1403 writeEncodingPreamble(os, features);
1406 if (!features.runparams().includeall && !included_children_.empty()) {
1407 os << "\\includeonly{";
1408 list<string>::const_iterator it = included_children_.begin();
1409 list<string>::const_iterator en = included_children_.end();
1411 for (; it != en; ++it) {
1412 string incfile = *it;
1413 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1414 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1416 if (!features.runparams().nice)
1418 // \includeonly doesn't want an extension
1419 incfile = changeExtension(incfile, string());
1420 incfile = support::latex_path(incfile);
1421 if (!incfile.empty()) {
1424 os << from_utf8(incfile);
1431 if (!listings_params.empty() || features.isRequired("listings"))
1432 os << "\\usepackage{listings}\n";
1434 if (!listings_params.empty()) {
1436 // do not test validity because listings_params is
1437 // supposed to be valid
1439 InsetListingsParams(listings_params).separatedParams(true);
1440 // we can't support all packages, but we should load the color package
1441 if (par.find("\\color", 0) != string::npos)
1442 features.require("color");
1443 os << from_utf8(par)
1446 if (!tclass.provides("geometry")
1447 && (use_geometry || nonstandard_papersize)) {
1448 odocstringstream ods;
1449 if (!getGraphicsDriver("geometry").empty())
1450 ods << getGraphicsDriver("geometry");
1451 if (orientation == ORIENTATION_LANDSCAPE)
1452 ods << ",landscape";
1453 switch (papersize) {
1455 if (!paperwidth.empty())
1456 ods << ",paperwidth="
1457 << from_ascii(paperwidth);
1458 if (!paperheight.empty())
1459 ods << ",paperheight="
1460 << from_ascii(paperheight);
1462 case PAPER_USLETTER:
1463 ods << ",letterpaper";
1466 ods << ",legalpaper";
1468 case PAPER_USEXECUTIVE:
1469 ods << ",executivepaper";
1556 // default papersize ie PAPER_DEFAULT
1557 switch (lyxrc.default_papersize) {
1558 case PAPER_DEFAULT: // keep compiler happy
1560 case PAPER_USLETTER:
1561 ods << ",letterpaper";
1564 ods << ",legalpaper";
1566 case PAPER_USEXECUTIVE:
1567 ods << ",executivepaper";
1609 docstring const g_options = trim(ods.str(), ",");
1610 os << "\\usepackage";
1611 if (!g_options.empty())
1612 os << '[' << g_options << ']';
1613 os << "{geometry}\n";
1614 // output this only if use_geometry is true
1616 os << "\\geometry{verbose";
1617 if (!topmargin.empty())
1618 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1619 if (!bottommargin.empty())
1620 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1621 if (!leftmargin.empty())
1622 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1623 if (!rightmargin.empty())
1624 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1625 if (!headheight.empty())
1626 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1627 if (!headsep.empty())
1628 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1629 if (!footskip.empty())
1630 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1631 if (!columnsep.empty())
1632 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1635 } else if (orientation == ORIENTATION_LANDSCAPE
1636 || papersize != PAPER_DEFAULT) {
1637 features.require("papersize");
1640 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1641 if (pagestyle == "fancy")
1642 os << "\\usepackage{fancyhdr}\n";
1643 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1646 // only output when the background color is not default
1647 if (isbackgroundcolor == true) {
1648 // only require color here, the background color will be defined
1649 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1651 features.require("color");
1652 features.require("pagecolor");
1655 // only output when the font color is not default
1656 if (isfontcolor == true) {
1657 // only require color here, the font color will be defined
1658 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1660 features.require("color");
1661 features.require("fontcolor");
1664 // Only if class has a ToC hierarchy
1665 if (tclass.hasTocLevels()) {
1666 if (secnumdepth != tclass.secnumdepth()) {
1667 os << "\\setcounter{secnumdepth}{"
1671 if (tocdepth != tclass.tocdepth()) {
1672 os << "\\setcounter{tocdepth}{"
1678 if (paragraph_separation) {
1679 // when skip separation
1680 switch (getDefSkip().kind()) {
1681 case VSpace::SMALLSKIP:
1682 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1684 case VSpace::MEDSKIP:
1685 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1687 case VSpace::BIGSKIP:
1688 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1690 case VSpace::LENGTH:
1691 os << "\\setlength{\\parskip}{"
1692 << from_utf8(getDefSkip().length().asLatexString())
1695 default: // should never happen // Then delete it.
1696 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1699 os << "\\setlength{\\parindent}{0pt}\n";
1701 // when separation by indentation
1702 // only output something when a width is given
1703 if (getIndentation().asLyXCommand() != "default") {
1704 os << "\\setlength{\\parindent}{"
1705 << from_utf8(getIndentation().asLatexCommand())
1710 // Now insert the LyX specific LaTeX commands...
1711 docstring lyxpreamble;
1714 if (!output_sync_macro.empty())
1715 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1716 else if (features.runparams().flavor == OutputParams::LATEX)
1717 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1718 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1719 lyxpreamble += "\\synctex=-1\n";
1722 // due to interferences with babel and hyperref, the color package has to
1723 // be loaded (when it is not already loaded) before babel when hyperref
1724 // is used with the colorlinks option, see
1725 // http://www.lyx.org/trac/ticket/5291
1726 // we decided therefore to load color always before babel, see
1727 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1728 lyxpreamble += from_ascii(features.getColorOptions());
1730 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1732 && (features.isRequired("jurabib")
1733 || features.isRequired("hyperref")
1734 || features.isRequired("vietnamese")
1735 || features.isRequired("japanese"))) {
1737 lyxpreamble += from_utf8(features.getBabelPresettings());
1738 lyxpreamble += from_utf8(babelCall(language_options.str(),
1739 features.needBabelLangOptions())) + '\n';
1740 lyxpreamble += from_utf8(features.getBabelPostsettings());
1743 // The optional packages;
1744 lyxpreamble += from_ascii(features.getPackages());
1746 // Additional Indices
1747 if (features.isRequired("splitidx")) {
1748 IndicesList::const_iterator iit = indiceslist().begin();
1749 IndicesList::const_iterator iend = indiceslist().end();
1750 for (; iit != iend; ++iit) {
1751 lyxpreamble += "\\newindex[";
1752 lyxpreamble += iit->index();
1753 lyxpreamble += "]{";
1754 lyxpreamble += iit->shortcut();
1755 lyxpreamble += "}\n";
1760 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1763 // * Hyperref manual: "Make sure it comes last of your loaded
1764 // packages, to give it a fighting chance of not being over-written,
1765 // since its job is to redefine many LaTeX commands."
1766 // * Email from Heiko Oberdiek: "It is usually better to load babel
1767 // before hyperref. Then hyperref has a chance to detect babel.
1768 // * Has to be loaded before the "LyX specific LaTeX commands" to
1769 // avoid errors with algorithm floats.
1770 // use hyperref explicitly if it is required
1771 if (features.isRequired("hyperref")) {
1772 // pass what we have to stream here, since we need
1773 // to access the stream itself in PDFOptions.
1776 OutputParams tmp_params = features.runparams();
1777 pdfoptions().writeLaTeX(tmp_params, os,
1778 documentClass().provides("hyperref"));
1779 // set back for the rest
1780 lyxpreamble.clear();
1781 // correctly break URLs with hyperref and dvi output
1782 if (features.runparams().flavor == OutputParams::LATEX
1783 && features.isAvailable("breakurl"))
1784 lyxpreamble += "\\usepackage{breakurl}\n";
1785 } else if (features.isRequired("nameref"))
1786 // hyperref loads this automatically
1787 lyxpreamble += "\\usepackage{nameref}\n";
1789 // Will be surrounded by \makeatletter and \makeatother when not empty
1790 docstring atlyxpreamble;
1792 // Some macros LyX will need
1793 docstring tmppreamble(features.getMacros());
1795 if (!tmppreamble.empty())
1796 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1797 "LyX specific LaTeX commands.\n"
1798 + tmppreamble + '\n';
1800 // the text class specific preamble
1801 tmppreamble = features.getTClassPreamble();
1802 if (!tmppreamble.empty())
1803 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1804 "Textclass specific LaTeX commands.\n"
1805 + tmppreamble + '\n';
1807 // suppress date if selected
1808 // use \@ifundefined because we cannot be sure that every document class
1809 // has a \date command
1811 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1813 /* the user-defined preamble */
1814 if (!containsOnly(preamble, " \n\t"))
1816 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1817 "User specified LaTeX commands.\n"
1818 + from_utf8(preamble) + '\n';
1820 // subfig loads internally the LaTeX package "caption". As
1821 // caption is a very popular package, users will load it in
1822 // the preamble. Therefore we must load subfig behind the
1823 // user-defined preamble and check if the caption package was
1824 // loaded or not. For the case that caption is loaded before
1825 // subfig, there is the subfig option "caption=false". This
1826 // option also works when a koma-script class is used and
1827 // koma's own caption commands are used instead of caption. We
1828 // use \PassOptionsToPackage here because the user could have
1829 // already loaded subfig in the preamble.
1830 if (features.isRequired("subfig")) {
1831 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1832 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1833 "\\usepackage{subfig}\n";
1836 // Itemize bullet settings need to be last in case the user
1837 // defines their own bullets that use a package included
1838 // in the user-defined preamble -- ARRae
1839 // Actually it has to be done much later than that
1840 // since some packages like frenchb make modifications
1841 // at \begin{document} time -- JMarc
1842 docstring bullets_def;
1843 for (int i = 0; i < 4; ++i) {
1844 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1845 if (bullets_def.empty())
1846 bullets_def += "\\AtBeginDocument{\n";
1847 bullets_def += " \\def\\labelitemi";
1849 // `i' is one less than the item to modify
1856 bullets_def += "ii";
1862 bullets_def += '{' +
1863 user_defined_bullet(i).getText()
1868 if (!bullets_def.empty())
1869 atlyxpreamble += bullets_def + "}\n\n";
1871 if (!atlyxpreamble.empty())
1872 lyxpreamble += "\n\\makeatletter\n"
1873 + atlyxpreamble + "\\makeatother\n\n";
1875 // We try to load babel late, in case it interferes with other packages.
1876 // Jurabib and Hyperref have to be called after babel, though.
1877 if (use_babel && !features.isRequired("jurabib")
1878 && !features.isRequired("hyperref")
1879 && !features.isRequired("vietnamese")
1880 && !features.isRequired("japanese")) {
1882 lyxpreamble += from_utf8(features.getBabelPresettings());
1883 lyxpreamble += from_utf8(babelCall(language_options.str(),
1884 features.needBabelLangOptions())) + '\n';
1885 lyxpreamble += from_utf8(features.getBabelPostsettings());
1888 // xunicode needs to be loaded at least after amsmath, amssymb,
1889 // esint and the other packages that provide special glyphs
1890 if (features.runparams().flavor == OutputParams::XETEX)
1891 lyxpreamble += "\\usepackage{xunicode}\n";
1893 // Polyglossia must be loaded last
1894 if (use_polyglossia) {
1896 lyxpreamble += "\\usepackage{polyglossia}\n";
1897 // set the main language
1898 lyxpreamble += "\\setdefaultlanguage";
1899 if (!language->polyglossiaOpts().empty())
1900 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1901 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1902 // now setup the other languages
1903 std::map<std::string, std::string> const polylangs =
1904 features.getPolyglossiaLanguages();
1905 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1906 mit != polylangs.end() ; ++mit) {
1907 lyxpreamble += "\\setotherlanguage";
1908 if (!mit->second.empty())
1909 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1910 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
1914 docstring const i18npreamble =
1915 features.getTClassI18nPreamble(use_babel, use_polyglossia);
1916 if (!i18npreamble.empty())
1917 lyxpreamble += i18npreamble + '\n';
1925 void BufferParams::useClassDefaults()
1927 DocumentClass const & tclass = documentClass();
1929 sides = tclass.sides();
1930 columns = tclass.columns();
1931 pagestyle = tclass.pagestyle();
1932 use_default_options = true;
1933 // Only if class has a ToC hierarchy
1934 if (tclass.hasTocLevels()) {
1935 secnumdepth = tclass.secnumdepth();
1936 tocdepth = tclass.tocdepth();
1941 bool BufferParams::hasClassDefaults() const
1943 DocumentClass const & tclass = documentClass();
1945 return sides == tclass.sides()
1946 && columns == tclass.columns()
1947 && pagestyle == tclass.pagestyle()
1948 && use_default_options
1949 && secnumdepth == tclass.secnumdepth()
1950 && tocdepth == tclass.tocdepth();
1954 DocumentClass const & BufferParams::documentClass() const
1960 DocumentClass const * BufferParams::documentClassPtr() const
1966 void BufferParams::setDocumentClass(DocumentClass const * const tc)
1968 // evil, but this function is evil
1969 doc_class_ = const_cast<DocumentClass *>(tc);
1973 bool BufferParams::setBaseClass(string const & classname)
1975 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1976 LayoutFileList & bcl = LayoutFileList::get();
1977 if (!bcl.haveClass(classname)) {
1979 bformat(_("The layout file:\n"
1981 "could not be found. A default textclass with default\n"
1982 "layouts will be used. LyX will not be able to produce\n"
1984 from_utf8(classname));
1985 frontend::Alert::error(_("Document class not found"), s);
1986 bcl.addEmptyClass(classname);
1989 bool const success = bcl[classname].load();
1992 bformat(_("Due to some error in it, the layout file:\n"
1994 "could not be loaded. A default textclass with default\n"
1995 "layouts will be used. LyX will not be able to produce\n"
1997 from_utf8(classname));
1998 frontend::Alert::error(_("Could not load class"), s);
1999 bcl.addEmptyClass(classname);
2002 pimpl_->baseClass_ = classname;
2003 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2008 LayoutFile const * BufferParams::baseClass() const
2010 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2011 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2017 LayoutFileIndex const & BufferParams::baseClassID() const
2019 return pimpl_->baseClass_;
2023 void BufferParams::makeDocumentClass()
2028 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layout_modules_));
2030 if (!local_layout.empty()) {
2031 TextClass::ReturnValues success =
2032 doc_class_->read(local_layout, TextClass::MODULE);
2033 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2034 docstring const msg = _("Error reading internal layout information");
2035 frontend::Alert::warning(_("Read Error"), msg);
2041 bool BufferParams::moduleCanBeAdded(string const & modName) const
2043 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2047 bool BufferParams::addLayoutModule(string const & modName)
2049 LayoutModuleList::const_iterator it = layout_modules_.begin();
2050 LayoutModuleList::const_iterator end = layout_modules_.end();
2051 for (; it != end; it++)
2054 layout_modules_.push_back(modName);
2059 string BufferParams::bufferFormat() const
2061 string format = documentClass().outputFormat();
2062 if (format == "latex") {
2065 if (encoding().package() == Encoding::japanese)
2072 bool BufferParams::isExportable(string const & format) const
2074 vector<string> backs = backends();
2075 for (vector<string>::const_iterator it = backs.begin();
2076 it != backs.end(); ++it)
2077 if (theConverters().isReachable(*it, format))
2083 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2085 vector<string> const backs = backends();
2086 set<string> excludes;
2087 if (useNonTeXFonts) {
2088 excludes.insert("latex");
2089 excludes.insert("pdflatex");
2091 vector<Format const *> result =
2092 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2093 for (vector<string>::const_iterator it = backs.begin() + 1;
2094 it != backs.end(); ++it) {
2095 vector<Format const *> r =
2096 theConverters().getReachable(*it, only_viewable, false, excludes);
2097 result.insert(result.end(), r.begin(), r.end());
2103 bool BufferParams::isExportableFormat(string const & format) const
2105 typedef vector<Format const *> Formats;
2107 formats = exportableFormats(true);
2108 Formats::const_iterator fit = formats.begin();
2109 Formats::const_iterator end = formats.end();
2110 for (; fit != end ; ++fit) {
2111 if ((*fit)->name() == format)
2118 vector<string> BufferParams::backends() const
2121 v.push_back(bufferFormat());
2122 // FIXME: Don't hardcode format names here, but use a flag
2123 if (v.back() == "latex") {
2124 v.push_back("pdflatex");
2125 v.push_back("luatex");
2126 v.push_back("dviluatex");
2127 v.push_back("xetex");
2128 } else if (v.back() == "xetex") {
2129 v.push_back("luatex");
2130 v.push_back("dviluatex");
2132 v.push_back("xhtml");
2133 v.push_back("text");
2139 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const format) const
2141 string const dformat = (format.empty() || format == "default") ?
2142 getDefaultOutputFormat() : format;
2143 DefaultFlavorCache::const_iterator it =
2144 default_flavors_.find(dformat);
2146 if (it != default_flavors_.end())
2149 OutputParams::FLAVOR result = OutputParams::LATEX;
2151 if (dformat == "xhtml")
2152 result = OutputParams::HTML;
2154 // Try to determine flavor of default output format
2155 vector<string> backs = backends();
2156 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2157 // Get shortest path to format
2158 Graph::EdgePath path;
2159 for (vector<string>::const_iterator it = backs.begin();
2160 it != backs.end(); ++it) {
2161 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2162 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2167 result = theConverters().getFlavor(path);
2170 // cache this flavor
2171 default_flavors_[dformat] = result;
2176 string BufferParams::getDefaultOutputFormat() const
2178 if (!default_output_format.empty()
2179 && default_output_format != "default")
2180 return default_output_format;
2183 || encoding().package() == Encoding::japanese) {
2184 vector<Format const *> const formats = exportableFormats(true);
2185 if (formats.empty())
2187 // return the first we find
2188 return formats.front()->name();
2190 return lyxrc.default_view_format;
2193 Font const BufferParams::getFont() const
2195 FontInfo f = documentClass().defaultfont();
2196 if (fonts_default_family == "rmdefault")
2197 f.setFamily(ROMAN_FAMILY);
2198 else if (fonts_default_family == "sfdefault")
2199 f.setFamily(SANS_FAMILY);
2200 else if (fonts_default_family == "ttdefault")
2201 f.setFamily(TYPEWRITER_FAMILY);
2202 return Font(f, language);
2206 bool BufferParams::isLatex() const
2208 return documentClass().outputType() == LATEX;
2212 bool BufferParams::isLiterate() const
2214 return documentClass().outputType() == LITERATE;
2218 bool BufferParams::isDocBook() const
2220 return documentClass().outputType() == DOCBOOK;
2224 void BufferParams::readPreamble(Lexer & lex)
2226 if (lex.getString() != "\\begin_preamble")
2227 lyxerr << "Error (BufferParams::readPreamble):"
2228 "consistency check failed." << endl;
2230 preamble = lex.getLongString("\\end_preamble");
2234 void BufferParams::readLocalLayout(Lexer & lex)
2236 if (lex.getString() != "\\begin_local_layout")
2237 lyxerr << "Error (BufferParams::readLocalLayout):"
2238 "consistency check failed." << endl;
2240 local_layout = lex.getLongString("\\end_local_layout");
2244 bool BufferParams::setLanguage(string const & lang)
2246 Language const *new_language = languages.getLanguage(lang);
2247 if (!new_language) {
2248 // Language lang was not found
2251 language = new_language;
2256 void BufferParams::readLanguage(Lexer & lex)
2258 if (!lex.next()) return;
2260 string const tmptok = lex.getString();
2262 // check if tmptok is part of tex_babel in tex-defs.h
2263 if (!setLanguage(tmptok)) {
2264 // Language tmptok was not found
2265 language = default_language;
2266 lyxerr << "Warning: Setting language `"
2267 << tmptok << "' to `" << language->lang()
2273 void BufferParams::readGraphicsDriver(Lexer & lex)
2278 string const tmptok = lex.getString();
2279 // check if tmptok is part of tex_graphics in tex_defs.h
2282 string const test = tex_graphics[n++];
2284 if (test == tmptok) {
2285 graphics_driver = tmptok;
2290 "Warning: graphics driver `$$Token' not recognized!\n"
2291 " Setting graphics driver to `default'.\n");
2292 graphics_driver = "default";
2299 void BufferParams::readBullets(Lexer & lex)
2304 int const index = lex.getInteger();
2306 int temp_int = lex.getInteger();
2307 user_defined_bullet(index).setFont(temp_int);
2308 temp_bullet(index).setFont(temp_int);
2310 user_defined_bullet(index).setCharacter(temp_int);
2311 temp_bullet(index).setCharacter(temp_int);
2313 user_defined_bullet(index).setSize(temp_int);
2314 temp_bullet(index).setSize(temp_int);
2318 void BufferParams::readBulletsLaTeX(Lexer & lex)
2320 // The bullet class should be able to read this.
2323 int const index = lex.getInteger();
2325 docstring const temp_str = lex.getDocString();
2327 user_defined_bullet(index).setText(temp_str);
2328 temp_bullet(index).setText(temp_str);
2332 void BufferParams::readModules(Lexer & lex)
2334 if (!lex.eatLine()) {
2335 lyxerr << "Error (BufferParams::readModules):"
2336 "Unexpected end of input." << endl;
2340 string mod = lex.getString();
2341 if (mod == "\\end_modules")
2343 addLayoutModule(mod);
2349 void BufferParams::readRemovedModules(Lexer & lex)
2351 if (!lex.eatLine()) {
2352 lyxerr << "Error (BufferParams::readRemovedModules):"
2353 "Unexpected end of input." << endl;
2357 string mod = lex.getString();
2358 if (mod == "\\end_removed_modules")
2360 removed_modules_.push_back(mod);
2363 // now we want to remove any removed modules that were previously
2364 // added. normally, that will be because default modules were added in
2365 // setBaseClass(), which gets called when \textclass is read at the
2366 // start of the read.
2367 list<string>::const_iterator rit = removed_modules_.begin();
2368 list<string>::const_iterator const ren = removed_modules_.end();
2369 for (; rit != ren; rit++) {
2370 LayoutModuleList::iterator const mit = layout_modules_.begin();
2371 LayoutModuleList::iterator const men = layout_modules_.end();
2372 LayoutModuleList::iterator found = find(mit, men, *rit);
2375 layout_modules_.erase(found);
2380 void BufferParams::readIncludeonly(Lexer & lex)
2382 if (!lex.eatLine()) {
2383 lyxerr << "Error (BufferParams::readIncludeonly):"
2384 "Unexpected end of input." << endl;
2388 string child = lex.getString();
2389 if (child == "\\end_includeonly")
2391 included_children_.push_back(child);
2397 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2399 char real_papersize = papersize;
2400 if (real_papersize == PAPER_DEFAULT)
2401 real_papersize = lyxrc.default_papersize;
2403 switch (real_papersize) {
2405 // could be anything, so don't guess
2407 case PAPER_CUSTOM: {
2408 if (purpose == XDVI && !paperwidth.empty() &&
2409 !paperheight.empty()) {
2410 // heightxwidth<unit>
2411 string first = paperwidth;
2412 string second = paperheight;
2413 if (orientation == ORIENTATION_LANDSCAPE)
2416 return first.erase(first.length() - 2)
2422 // dvips and dvipdfm do not know this
2423 if (purpose == DVIPS || purpose == DVIPDFM)
2427 if (purpose == DVIPS || purpose == DVIPDFM)
2431 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 if (purpose == DVIPS || purpose == DVIPDFM)
2461 // dvipdfm does not know this
2462 if (purpose == DVIPDFM)
2466 if (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)
2526 if (purpose == DVIPS || purpose == DVIPDFM)
2529 case PAPER_USEXECUTIVE:
2530 // dvipdfm does not know this
2531 if (purpose == DVIPDFM)
2536 case PAPER_USLETTER:
2538 if (purpose == XDVI)
2545 string const BufferParams::dvips_options() const
2550 && papersize == PAPER_CUSTOM
2551 && !lyxrc.print_paper_dimension_flag.empty()
2552 && !paperwidth.empty()
2553 && !paperheight.empty()) {
2554 // using a custom papersize
2555 result = lyxrc.print_paper_dimension_flag;
2556 result += ' ' + paperwidth;
2557 result += ',' + paperheight;
2559 string const paper_option = paperSizeName(DVIPS);
2560 if (!paper_option.empty() && (paper_option != "letter" ||
2561 orientation != ORIENTATION_LANDSCAPE)) {
2562 // dvips won't accept -t letter -t landscape.
2563 // In all other cases, include the paper size
2565 result = lyxrc.print_paper_flag;
2566 result += ' ' + paper_option;
2569 if (orientation == ORIENTATION_LANDSCAPE &&
2570 papersize != PAPER_CUSTOM)
2571 result += ' ' + lyxrc.print_landscape_flag;
2576 string const BufferParams::font_encoding() const
2578 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2582 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2584 if (lang_package != "auto" && lang_package != "babel"
2585 && lang_package != "default" && lang_package != "none")
2586 return lang_package;
2587 if (lyxrc.language_package_selection == LyXRC::LP_CUSTOM)
2588 return lyxrc.language_custom_package;
2589 // suppress the babel call if there is no BabelName defined
2590 // for the document language in the lib/languages file and if no
2591 // other languages are used (lang_opts is then empty)
2592 if (lang_opts.empty())
2594 // either a specific language (AsBabelOptions setting in
2595 // lib/languages) or the prefs require the languages to
2596 // be submitted to babel itself (not the class).
2598 return "\\usepackage[" + lang_opts + "]{babel}";
2599 return "\\usepackage{babel}";
2603 docstring BufferParams::getGraphicsDriver(string const & package) const
2607 if (package == "geometry") {
2608 if (graphics_driver == "dvips"
2609 || graphics_driver == "dvipdfm"
2610 || graphics_driver == "pdftex"
2611 || graphics_driver == "vtex")
2612 result = from_ascii(graphics_driver);
2613 else if (graphics_driver == "dvipdfmx")
2614 result = from_ascii("dvipdfm");
2621 void BufferParams::writeEncodingPreamble(otexstream & os,
2622 LaTeXFeatures & features) const
2624 // XeTeX does not need this
2625 if (features.runparams().flavor == OutputParams::XETEX)
2627 // LuaTeX neither, but with tex fonts, we need to load
2628 // the luainputenc package.
2629 if (features.runparams().flavor == OutputParams::LUATEX
2630 || features.runparams().flavor == OutputParams::DVILUATEX) {
2631 if (!useNonTeXFonts && inputenc != "default"
2632 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2633 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2634 os << "\\usepackage[utf8]{luainputenc}\n";
2638 if (inputenc == "auto") {
2639 string const doc_encoding =
2640 language->encoding()->latexName();
2641 Encoding::Package const package =
2642 language->encoding()->package();
2644 // Create a list with all the input encodings used
2646 set<string> encodings =
2647 features.getEncodingSet(doc_encoding);
2649 // If the "japanese" package (i.e. pLaTeX) is used,
2650 // inputenc must be omitted.
2651 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2652 if (package == Encoding::japanese)
2653 features.require("japanese");
2655 if ((!encodings.empty() || package == Encoding::inputenc)
2656 && !features.isRequired("japanese")) {
2657 os << "\\usepackage[";
2658 set<string>::const_iterator it = encodings.begin();
2659 set<string>::const_iterator const end = encodings.end();
2661 os << from_ascii(*it);
2664 for (; it != end; ++it)
2665 os << ',' << from_ascii(*it);
2666 if (package == Encoding::inputenc) {
2667 if (!encodings.empty())
2669 os << from_ascii(doc_encoding);
2671 os << "]{inputenc}\n";
2673 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2674 if (language->encoding()->name() == "utf8-cjk"
2675 && LaTeXFeatures::isAvailable("CJKutf8"))
2676 os << "\\usepackage{CJKutf8}\n";
2678 os << "\\usepackage{CJK}\n";
2680 } else if (inputenc != "default") {
2681 switch (encoding().package()) {
2682 case Encoding::none:
2683 case Encoding::japanese:
2685 case Encoding::inputenc:
2686 // do not load inputenc if japanese is used
2687 if (features.isRequired("japanese"))
2689 os << "\\usepackage[" << from_ascii(inputenc)
2693 if (encoding().name() == "utf8-cjk"
2694 && LaTeXFeatures::isAvailable("CJKutf8"))
2695 os << "\\usepackage{CJKutf8}\n";
2697 os << "\\usepackage{CJK}\n";
2702 // The encoding "armscii8" (for Armenian) is only available when
2703 // the package "armtex" is loaded.
2704 if (language->encoding()->latexName() == "armscii8"
2705 || inputenc == "armscii8")
2706 os << "\\usepackage{armtex}\n";
2710 string const BufferParams::parseFontName(string const & name) const
2712 string mangled = name;
2713 size_t const idx = mangled.find('[');
2714 if (idx == string::npos || idx == 0)
2717 return mangled.substr(0, idx - 1);
2721 string const BufferParams::loadFonts(string const & rm,
2722 string const & sf, string const & tt,
2723 bool const & sc, bool const & osf,
2724 int const & sfscale, int const & ttscale,
2725 bool const & use_systemfonts,
2726 LaTeXFeatures & features) const
2728 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2729 several packages have been replaced by others, that might not
2730 be installed on every system. We have to take care for that
2731 (see psnfss.pdf). We try to support all psnfss fonts as well
2732 as the fonts that have become de facto standard in the LaTeX
2733 world (e.g. Latin Modern). We do not support obsolete fonts
2734 (like PSLatex). In general, it should be possible to mix any
2735 rm font with any sf or tt font, respectively. (JSpitzm)
2737 -- separate math fonts.
2740 if (rm == "default" && sf == "default" && tt == "default")
2746 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2747 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2748 * Mapping=tex-text option assures TeX ligatures (such as "--")
2749 * are resolved. Note that tt does not use these ligatures.
2751 * -- add more GUI options?
2752 * -- add more fonts (fonts for other scripts)
2753 * -- if there's a way to find out if a font really supports
2754 * OldStyle, enable/disable the widget accordingly.
2756 if (use_systemfonts && features.isAvailable("fontspec")) {
2757 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2758 // However, until v.2 (2010/07/11) fontspec only knew
2759 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2760 // was introduced for both XeTeX and LuaTeX (LuaTeX
2761 // didn't understand "Mapping=tex-text", while XeTeX
2762 // understood both. With most recent versions, both
2763 // variants are understood by both engines. However,
2764 // we want to provide support for at least TeXLive 2009
2765 // (for XeTeX; LuaTeX is only supported as of v.2)
2766 string const texmapping =
2767 (features.runparams().flavor == OutputParams::XETEX) ?
2768 "Mapping=tex-text" : "Ligatures=TeX";
2769 if (rm != "default") {
2770 os << "\\setmainfont[" << texmapping;
2772 os << ",Numbers=OldStyle";
2773 os << "]{" << parseFontName(rm) << "}\n";
2775 if (sf != "default") {
2776 string const sans = parseFontName(sf);
2778 os << "\\setsansfont[Scale="
2779 << float(sfscale) / 100
2780 << "," << texmapping << "]{"
2783 os << "\\setsansfont[" << texmapping << "]{"
2786 if (tt != "default") {
2787 string const mono = parseFontName(tt);
2789 os << "\\setmonofont[Scale="
2790 << float(ttscale) / 100
2794 os << "\\setmonofont{"
2801 // Computer Modern (must be explicitly selectable -- there might be classes
2802 // that define a different default font!
2804 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2805 // osf for Computer Modern needs eco.sty
2807 os << "\\usepackage{eco}\n";
2809 // Latin Modern Roman
2810 else if (rm == "lmodern")
2811 os << "\\usepackage{lmodern}\n";
2813 else if (rm == "ae") {
2814 // not needed when using OT1 font encoding.
2815 if (font_encoding() != "default")
2816 os << "\\usepackage{ae,aecompl}\n";
2819 else if (rm == "times") {
2820 // try to load the best available package
2821 if (LaTeXFeatures::isAvailable("mathptmx"))
2822 os << "\\usepackage{mathptmx}\n";
2823 else if (LaTeXFeatures::isAvailable("mathptm"))
2824 os << "\\usepackage{mathptm}\n";
2826 os << "\\usepackage{times}\n";
2829 else if (rm == "palatino") {
2830 // try to load the best available package
2831 if (LaTeXFeatures::isAvailable("mathpazo")) {
2832 os << "\\usepackage";
2838 // "osf" includes "sc"!
2842 os << "{mathpazo}\n";
2844 else if (LaTeXFeatures::isAvailable("mathpple"))
2845 os << "\\usepackage{mathpple}\n";
2847 os << "\\usepackage{palatino}\n";
2850 else if (rm == "utopia") {
2851 // fourier supersedes utopia.sty, but does
2852 // not work with OT1 encoding.
2853 if (LaTeXFeatures::isAvailable("fourier")
2854 && font_encoding() != "default") {
2855 os << "\\usepackage";
2866 os << "{fourier}\n";
2869 os << "\\usepackage{utopia}\n";
2871 // Bera (complete fontset)
2872 else if (rm == "bera" && sf == "default" && tt == "default")
2873 os << "\\usepackage{bera}\n";
2875 else if (rm != "default")
2876 os << "\\usepackage" << "{" << rm << "}\n";
2879 // Helvetica, Bera Sans
2880 if (sf == "helvet" || sf == "berasans") {
2882 os << "\\usepackage[scaled=" << float(sfscale) / 100
2883 << "]{" << sf << "}\n";
2885 os << "\\usepackage{" << sf << "}\n";
2888 else if (sf == "avant")
2889 os << "\\usepackage{" << sf << "}\n";
2890 // Computer Modern, Latin Modern, CM Bright
2891 else if (sf != "default")
2892 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2894 // monospaced/typewriter
2895 // Courier, LuxiMono
2896 if (tt == "luximono" || tt == "beramono") {
2898 os << "\\usepackage[scaled=" << float(ttscale) / 100
2899 << "]{" << tt << "}\n";
2901 os << "\\usepackage{" << tt << "}\n";
2904 else if (tt == "courier" )
2905 os << "\\usepackage{" << tt << "}\n";
2906 // Computer Modern, Latin Modern, CM Bright
2907 else if (tt != "default")
2908 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2914 Encoding const & BufferParams::encoding() const
2916 // FIXME: actually, we should check for the flavor
2917 // or runparams.isFullyUnicode() here:
2918 // This check will not work with XeTeX/LuaTeX and tex fonts.
2919 // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2921 return *(encodings.fromLaTeXName("utf8-plain"));
2922 if (inputenc == "auto" || inputenc == "default")
2923 return *language->encoding();
2924 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2927 LYXERR0("Unknown inputenc value `" << inputenc
2928 << "'. Using `auto' instead.");
2929 return *language->encoding();
2933 CiteEngine BufferParams::citeEngine() const
2935 // FIXME the class should provide the numerical/
2936 // authoryear choice
2937 if (documentClass().provides("natbib")
2938 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2939 return ENGINE_NATBIB_AUTHORYEAR;
2940 return cite_engine_;
2944 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2946 cite_engine_ = cite_engine;