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 "LaTeXFonts.h"
34 #include "ModuleList.h"
38 #include "OutputParams.h"
42 #include "PDFOptions.h"
44 #include "frontends/alert.h"
46 #include "insets/InsetListingsParams.h"
48 #include "support/convert.h"
49 #include "support/debug.h"
50 #include "support/docstream.h"
51 #include "support/FileName.h"
52 #include "support/filetools.h"
53 #include "support/gettext.h"
54 #include "support/Messages.h"
55 #include "support/Translator.h"
56 #include "support/lstrings.h"
62 using namespace lyx::support;
65 static char const * const string_paragraph_separation[] = {
70 static char const * const string_quotes_language[] = {
71 "english", "swedish", "german", "polish", "french", "danish", ""
75 static char const * const string_papersize[] = {
76 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
77 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
78 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
79 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
80 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
85 static char const * const string_orientation[] = {
86 "portrait", "landscape", ""
90 static char const * const string_footnotekinds[] = {
91 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
95 static char const * const tex_graphics[] = {
96 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
97 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
98 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
99 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
110 // Paragraph separation
111 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
114 ParSepTranslator const init_parseptranslator()
116 ParSepTranslator translator
117 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
118 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
123 ParSepTranslator const & parseptranslator()
125 static ParSepTranslator translator = init_parseptranslator();
131 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
134 QuotesLangTranslator const init_quoteslangtranslator()
136 QuotesLangTranslator translator
137 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
138 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
139 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
140 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
141 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
142 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
147 QuotesLangTranslator const & quoteslangtranslator()
149 static QuotesLangTranslator translator = init_quoteslangtranslator();
155 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
158 static PaperSizeTranslator initPaperSizeTranslator()
160 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
161 translator.addPair(string_papersize[1], PAPER_CUSTOM);
162 translator.addPair(string_papersize[2], PAPER_USLETTER);
163 translator.addPair(string_papersize[3], PAPER_USLEGAL);
164 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
165 translator.addPair(string_papersize[5], PAPER_A0);
166 translator.addPair(string_papersize[6], PAPER_A1);
167 translator.addPair(string_papersize[7], PAPER_A2);
168 translator.addPair(string_papersize[8], PAPER_A3);
169 translator.addPair(string_papersize[9], PAPER_A4);
170 translator.addPair(string_papersize[10], PAPER_A5);
171 translator.addPair(string_papersize[11], PAPER_A6);
172 translator.addPair(string_papersize[12], PAPER_B0);
173 translator.addPair(string_papersize[13], PAPER_B1);
174 translator.addPair(string_papersize[14], PAPER_B2);
175 translator.addPair(string_papersize[15], PAPER_B3);
176 translator.addPair(string_papersize[16], PAPER_B4);
177 translator.addPair(string_papersize[17], PAPER_B5);
178 translator.addPair(string_papersize[18], PAPER_B6);
179 translator.addPair(string_papersize[19], PAPER_C0);
180 translator.addPair(string_papersize[20], PAPER_C1);
181 translator.addPair(string_papersize[21], PAPER_C2);
182 translator.addPair(string_papersize[22], PAPER_C3);
183 translator.addPair(string_papersize[23], PAPER_C4);
184 translator.addPair(string_papersize[24], PAPER_C5);
185 translator.addPair(string_papersize[25], PAPER_C6);
186 translator.addPair(string_papersize[26], PAPER_JISB0);
187 translator.addPair(string_papersize[27], PAPER_JISB1);
188 translator.addPair(string_papersize[28], PAPER_JISB2);
189 translator.addPair(string_papersize[29], PAPER_JISB3);
190 translator.addPair(string_papersize[30], PAPER_JISB4);
191 translator.addPair(string_papersize[31], PAPER_JISB5);
192 translator.addPair(string_papersize[32], PAPER_JISB6);
197 PaperSizeTranslator const & papersizetranslator()
199 static PaperSizeTranslator translator = initPaperSizeTranslator();
205 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
208 PaperOrientationTranslator const init_paperorientationtranslator()
210 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
211 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
216 PaperOrientationTranslator const & paperorientationtranslator()
218 static PaperOrientationTranslator translator = init_paperorientationtranslator();
224 typedef Translator<int, PageSides> SidesTranslator;
227 SidesTranslator const init_sidestranslator()
229 SidesTranslator translator(1, OneSide);
230 translator.addPair(2, TwoSides);
235 SidesTranslator const & sidestranslator()
237 static SidesTranslator translator = init_sidestranslator();
243 typedef Translator<int, BufferParams::Package> PackageTranslator;
246 PackageTranslator const init_packagetranslator()
248 PackageTranslator translator(0, BufferParams::package_off);
249 translator.addPair(1, BufferParams::package_auto);
250 translator.addPair(2, BufferParams::package_on);
255 PackageTranslator const & packagetranslator()
257 static PackageTranslator translator = init_packagetranslator();
263 typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
266 CiteEngineTypeTranslator const init_citeenginetypetranslator()
268 CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
269 translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
274 CiteEngineTypeTranslator const & citeenginetypetranslator()
276 static CiteEngineTypeTranslator translator = init_citeenginetypetranslator();
282 typedef Translator<string, Spacing::Space> SpaceTranslator;
285 SpaceTranslator const init_spacetranslator()
287 SpaceTranslator translator("default", Spacing::Default);
288 translator.addPair("single", Spacing::Single);
289 translator.addPair("onehalf", Spacing::Onehalf);
290 translator.addPair("double", Spacing::Double);
291 translator.addPair("other", Spacing::Other);
296 SpaceTranslator const & spacetranslator()
298 static SpaceTranslator translator = init_spacetranslator();
305 class BufferParams::Impl
310 AuthorList authorlist;
311 BranchList branchlist;
312 Bullet temp_bullets[4];
313 Bullet user_defined_bullets[4];
314 IndicesList indiceslist;
316 /** This is the amount of space used for paragraph_separation "skip",
317 * and for detached paragraphs in "indented" documents.
321 PDFOptions pdfoptions;
322 LayoutFileIndex baseClass_;
326 BufferParams::Impl::Impl()
327 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
329 // set initial author
331 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
336 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
340 return new BufferParams::Impl(*ptr);
344 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
350 BufferParams::BufferParams()
353 setBaseClass(defaultBaseclass());
355 paragraph_separation = ParagraphIndentSeparation;
356 quotes_language = InsetQuotes::EnglishQuotes;
357 fontsize = "default";
360 papersize = PAPER_DEFAULT;
361 orientation = ORIENTATION_PORTRAIT;
362 use_geometry = false;
363 cite_engine_.push_back("basic");
364 cite_engine_type_ = ENGINE_TYPE_NUMERICAL;
365 biblio_style = "plain";
366 use_bibtopic = false;
368 trackChanges = false;
369 outputChanges = false;
370 use_default_options = true;
371 maintain_unincluded_children = false;
374 language = default_language;
376 fonts_roman = "default";
377 fonts_sans = "default";
378 fonts_typewriter = "default";
379 fonts_default_family = "default";
380 useNonTeXFonts = false;
381 fonts_expert_sc = false;
382 fonts_old_figures = false;
383 fonts_sans_scale = 100;
384 fonts_typewriter_scale = 100;
386 lang_package = "default";
387 graphics_driver = "default";
388 default_output_format = "default";
389 bibtex_command = "default";
390 index_command = "default";
393 listings_params = string();
394 pagestyle = "default";
395 suppress_date = false;
396 justification = true;
397 // no color is the default (white)
398 backgroundcolor = lyx::rgbFromHexName("#ffffff");
399 isbackgroundcolor = false;
400 // no color is the default (black)
401 fontcolor = lyx::rgbFromHexName("#000000");
403 // light gray is the default font color for greyed-out notes
404 notefontcolor = lyx::rgbFromHexName("#cccccc");
405 boxbgcolor = lyx::rgbFromHexName("#ff0000");
406 compressed = lyxrc.save_compressed;
407 for (int iter = 0; iter < 4; ++iter) {
408 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
409 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
412 indiceslist().addDefault(B_("Index"));
413 html_be_strict = false;
414 html_math_output = MathML;
415 html_math_img_scale = 1.0;
416 html_css_as_file = false;
423 docstring BufferParams::B_(string const & l10n) const
425 LASSERT(language, /**/);
426 return getMessages(language->code()).get(l10n);
430 BufferParams::Package BufferParams::use_package(std::string const & p) const
432 PackageMap::const_iterator it = use_packages.find(p);
433 if (it == use_packages.end())
439 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
445 vector<string> const & BufferParams::auto_packages()
447 static vector<string> packages;
448 if (packages.empty()) {
449 // adding a package here implies a file format change!
450 packages.push_back("amsmath");
451 packages.push_back("amssymb");
452 packages.push_back("esint");
453 packages.push_back("mathdots");
454 packages.push_back("mathtools");
455 packages.push_back("mhchem");
456 packages.push_back("undertilde");
462 AuthorList & BufferParams::authors()
464 return pimpl_->authorlist;
468 AuthorList const & BufferParams::authors() const
470 return pimpl_->authorlist;
474 BranchList & BufferParams::branchlist()
476 return pimpl_->branchlist;
480 BranchList const & BufferParams::branchlist() const
482 return pimpl_->branchlist;
486 IndicesList & BufferParams::indiceslist()
488 return pimpl_->indiceslist;
492 IndicesList const & BufferParams::indiceslist() const
494 return pimpl_->indiceslist;
498 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
500 LASSERT(index < 4, /**/);
501 return pimpl_->temp_bullets[index];
505 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
507 LASSERT(index < 4, /**/);
508 return pimpl_->temp_bullets[index];
512 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
514 LASSERT(index < 4, /**/);
515 return pimpl_->user_defined_bullets[index];
519 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
521 LASSERT(index < 4, /**/);
522 return pimpl_->user_defined_bullets[index];
526 Spacing & BufferParams::spacing()
528 return pimpl_->spacing;
532 Spacing const & BufferParams::spacing() const
534 return pimpl_->spacing;
538 PDFOptions & BufferParams::pdfoptions()
540 return pimpl_->pdfoptions;
544 PDFOptions const & BufferParams::pdfoptions() const
546 return pimpl_->pdfoptions;
550 HSpace const & BufferParams::getIndentation() const
552 return pimpl_->indentation;
556 void BufferParams::setIndentation(HSpace const & indent)
558 pimpl_->indentation = indent;
562 VSpace const & BufferParams::getDefSkip() const
564 return pimpl_->defskip;
568 void BufferParams::setDefSkip(VSpace const & vs)
570 // DEFSKIP will cause an infinite loop
571 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
572 pimpl_->defskip = vs;
576 string BufferParams::readToken(Lexer & lex, string const & token,
577 FileName const & filepath)
579 if (token == "\\textclass") {
581 string const classname = lex.getString();
582 // if there exists a local layout file, ignore the system one
583 // NOTE: in this case, the textclass (.cls file) is assumed to
586 LayoutFileList & bcl = LayoutFileList::get();
587 if (tcp.empty() && !filepath.empty())
588 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
592 setBaseClass(classname);
593 // We assume that a tex class exists for local or unknown
594 // layouts so this warning, will only be given for system layouts.
595 if (!baseClass()->isTeXClassAvailable()) {
596 docstring const desc =
597 translateIfPossible(from_utf8(baseClass()->description()));
598 docstring const prereqs =
599 from_utf8(baseClass()->prerequisites());
600 docstring const msg =
601 bformat(_("The selected document class\n"
603 "requires external files that are not available.\n"
604 "The document class can still be used, but the\n"
605 "document cannot be compiled until the following\n"
606 "prerequisites are installed:\n"
608 "See section 3.1.2.2 (Class Availability) of the\n"
609 "User's Guide for more information."), desc, prereqs);
610 frontend::Alert::warning(_("Document class not available"),
613 } else if (token == "\\begin_preamble") {
615 } else if (token == "\\begin_local_layout") {
616 readLocalLayout(lex);
617 } else if (token == "\\begin_modules") {
619 } else if (token == "\\begin_removed_modules") {
620 readRemovedModules(lex);
621 } else if (token == "\\begin_includeonly") {
622 readIncludeonly(lex);
623 } else if (token == "\\maintain_unincluded_children") {
624 lex >> maintain_unincluded_children;
625 } else if (token == "\\options") {
627 options = lex.getString();
628 } else if (token == "\\use_default_options") {
629 lex >> use_default_options;
630 } else if (token == "\\master") {
632 master = lex.getString();
633 } else if (token == "\\suppress_date") {
634 lex >> suppress_date;
635 } else if (token == "\\justification") {
636 lex >> justification;
637 } else if (token == "\\language") {
639 } else if (token == "\\language_package") {
641 lang_package = lex.getString();
642 } else if (token == "\\inputencoding") {
644 } else if (token == "\\graphics") {
645 readGraphicsDriver(lex);
646 } else if (token == "\\default_output_format") {
647 lex >> default_output_format;
648 } else if (token == "\\bibtex_command") {
650 bibtex_command = lex.getString();
651 } else if (token == "\\index_command") {
653 index_command = lex.getString();
654 } else if (token == "\\fontencoding") {
656 fontenc = lex.getString();
657 } else if (token == "\\font_roman") {
659 fonts_roman = lex.getString();
660 } else if (token == "\\font_sans") {
662 fonts_sans = lex.getString();
663 } else if (token == "\\font_typewriter") {
665 fonts_typewriter = lex.getString();
666 } else if (token == "\\font_default_family") {
667 lex >> fonts_default_family;
668 } else if (token == "\\use_non_tex_fonts") {
669 lex >> useNonTeXFonts;
670 } else if (token == "\\font_sc") {
671 lex >> fonts_expert_sc;
672 } else if (token == "\\font_osf") {
673 lex >> fonts_old_figures;
674 } else if (token == "\\font_sf_scale") {
675 lex >> fonts_sans_scale;
676 } else if (token == "\\font_tt_scale") {
677 lex >> fonts_typewriter_scale;
678 } else if (token == "\\font_cjk") {
680 } else if (token == "\\paragraph_separation") {
683 paragraph_separation = parseptranslator().find(parsep);
684 } else if (token == "\\paragraph_indentation") {
686 string indentation = lex.getString();
687 pimpl_->indentation = HSpace(indentation);
688 } else if (token == "\\defskip") {
690 string const defskip = lex.getString();
691 pimpl_->defskip = VSpace(defskip);
692 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
694 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
695 } else if (token == "\\quotes_language") {
698 quotes_language = quoteslangtranslator().find(quotes_lang);
699 } else if (token == "\\papersize") {
702 papersize = papersizetranslator().find(ppsize);
703 } else if (token == "\\use_geometry") {
705 } else if (token == "\\use_package") {
710 use_package(package, packagetranslator().find(use));
711 } else if (token == "\\cite_engine") {
713 vector<string> engine = getVectorFromString(lex.getString());
714 setCiteEngine(engine);
715 } else if (token == "\\cite_engine_type") {
718 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
719 } else if (token == "\\biblio_style") {
721 biblio_style = lex.getString();
722 } else if (token == "\\use_bibtopic") {
724 } else if (token == "\\use_indices") {
726 } else if (token == "\\tracking_changes") {
728 } else if (token == "\\output_changes") {
729 lex >> outputChanges;
730 } else if (token == "\\branch") {
732 docstring branch = lex.getDocString();
733 branchlist().add(branch);
736 string const tok = lex.getString();
737 if (tok == "\\end_branch")
739 Branch * branch_ptr = branchlist().find(branch);
740 if (tok == "\\selected") {
743 branch_ptr->setSelected(lex.getInteger());
745 if (tok == "\\filename_suffix") {
748 branch_ptr->setFileNameSuffix(lex.getInteger());
750 if (tok == "\\color") {
752 string color = lex.getString();
754 branch_ptr->setColor(color);
755 // Update also the Color table:
757 color = lcolor.getX11Name(Color_background);
759 lcolor.setColor(to_utf8(branch), color);
762 } else if (token == "\\index") {
764 docstring index = lex.getDocString();
766 indiceslist().add(index);
769 string const tok = lex.getString();
770 if (tok == "\\end_index")
772 Index * index_ptr = indiceslist().find(index);
773 if (tok == "\\shortcut") {
775 shortcut = lex.getDocString();
777 index_ptr->setShortcut(shortcut);
779 if (tok == "\\color") {
781 string color = lex.getString();
783 index_ptr->setColor(color);
784 // Update also the Color table:
786 color = lcolor.getX11Name(Color_background);
788 if (!shortcut.empty())
789 lcolor.setColor(to_utf8(shortcut), color);
792 } else if (token == "\\author") {
794 istringstream ss(lex.getString());
797 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
798 } else if (token == "\\paperorientation") {
801 orientation = paperorientationtranslator().find(orient);
802 } else if (token == "\\backgroundcolor") {
804 backgroundcolor = lyx::rgbFromHexName(lex.getString());
805 isbackgroundcolor = true;
806 } else if (token == "\\fontcolor") {
808 fontcolor = lyx::rgbFromHexName(lex.getString());
810 } else if (token == "\\notefontcolor") {
812 string color = lex.getString();
813 notefontcolor = lyx::rgbFromHexName(color);
814 } else if (token == "\\boxbgcolor") {
816 string color = lex.getString();
817 boxbgcolor = lyx::rgbFromHexName(color);
818 } else if (token == "\\paperwidth") {
820 } else if (token == "\\paperheight") {
822 } else if (token == "\\leftmargin") {
824 } else if (token == "\\topmargin") {
826 } else if (token == "\\rightmargin") {
828 } else if (token == "\\bottommargin") {
830 } else if (token == "\\headheight") {
832 } else if (token == "\\headsep") {
834 } else if (token == "\\footskip") {
836 } else if (token == "\\columnsep") {
838 } else if (token == "\\paperfontsize") {
840 } else if (token == "\\papercolumns") {
842 } else if (token == "\\listings_params") {
845 listings_params = InsetListingsParams(par).params();
846 } else if (token == "\\papersides") {
849 sides = sidestranslator().find(psides);
850 } else if (token == "\\paperpagestyle") {
852 } else if (token == "\\bullet") {
854 } else if (token == "\\bulletLaTeX") {
855 readBulletsLaTeX(lex);
856 } else if (token == "\\secnumdepth") {
858 } else if (token == "\\tocdepth") {
860 } else if (token == "\\spacing") {
864 if (nspacing == "other") {
867 spacing().set(spacetranslator().find(nspacing), tmp_val);
868 } else if (token == "\\float_placement") {
869 lex >> float_placement;
871 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
872 string toktmp = pdfoptions().readToken(lex, token);
873 if (!toktmp.empty()) {
874 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
878 } else if (token == "\\html_math_output") {
881 html_math_output = static_cast<MathOutput>(temp);
882 } else if (token == "\\html_be_strict") {
883 lex >> html_be_strict;
884 } else if (token == "\\html_css_as_file") {
885 lex >> html_css_as_file;
886 } else if (token == "\\html_math_img_scale") {
887 lex >> html_math_img_scale;
888 } else if (token == "\\html_latex_start") {
890 html_latex_start = lex.getString();
891 } else if (token == "\\html_latex_end") {
893 html_latex_end = lex.getString();
894 } else if (token == "\\output_sync") {
896 } else if (token == "\\output_sync_macro") {
897 lex >> output_sync_macro;
898 } else if (token == "\\use_refstyle") {
901 lyxerr << "BufferParams::readToken(): Unknown token: " <<
910 void BufferParams::writeFile(ostream & os) const
912 // The top of the file is written by the buffer.
913 // Prints out the buffer info into the .lyx file given by file
916 os << "\\textclass " << baseClass()->name() << '\n';
919 if (!preamble.empty()) {
920 // remove '\n' from the end of preamble
921 string const tmppreamble = rtrim(preamble, "\n");
922 os << "\\begin_preamble\n"
924 << "\n\\end_preamble\n";
928 if (!options.empty()) {
929 os << "\\options " << options << '\n';
932 // use the class options defined in the layout?
933 os << "\\use_default_options "
934 << convert<string>(use_default_options) << "\n";
936 // the master document
937 if (!master.empty()) {
938 os << "\\master " << master << '\n';
942 if (!removed_modules_.empty()) {
943 os << "\\begin_removed_modules" << '\n';
944 list<string>::const_iterator it = removed_modules_.begin();
945 list<string>::const_iterator en = removed_modules_.end();
946 for (; it != en; ++it)
948 os << "\\end_removed_modules" << '\n';
952 if (!layout_modules_.empty()) {
953 os << "\\begin_modules" << '\n';
954 LayoutModuleList::const_iterator it = layout_modules_.begin();
955 LayoutModuleList::const_iterator en = layout_modules_.end();
956 for (; it != en; ++it)
958 os << "\\end_modules" << '\n';
962 if (!included_children_.empty()) {
963 os << "\\begin_includeonly" << '\n';
964 list<string>::const_iterator it = included_children_.begin();
965 list<string>::const_iterator en = included_children_.end();
966 for (; it != en; ++it)
968 os << "\\end_includeonly" << '\n';
970 os << "\\maintain_unincluded_children "
971 << convert<string>(maintain_unincluded_children) << '\n';
973 // local layout information
974 if (!local_layout.empty()) {
975 // remove '\n' from the end
976 string const tmplocal = rtrim(local_layout, "\n");
977 os << "\\begin_local_layout\n"
979 << "\n\\end_local_layout\n";
982 // then the text parameters
983 if (language != ignore_language)
984 os << "\\language " << language->lang() << '\n';
985 os << "\\language_package " << lang_package
986 << "\n\\inputencoding " << inputenc
987 << "\n\\fontencoding " << fontenc
988 << "\n\\font_roman " << fonts_roman
989 << "\n\\font_sans " << fonts_sans
990 << "\n\\font_typewriter " << fonts_typewriter
991 << "\n\\font_default_family " << fonts_default_family
992 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
993 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
994 << "\n\\font_osf " << convert<string>(fonts_old_figures)
995 << "\n\\font_sf_scale " << fonts_sans_scale
996 << "\n\\font_tt_scale " << fonts_typewriter_scale
998 if (!fonts_cjk.empty()) {
999 os << "\\font_cjk " << fonts_cjk << '\n';
1001 os << "\\graphics " << graphics_driver << '\n';
1002 os << "\\default_output_format " << default_output_format << '\n';
1003 os << "\\output_sync " << output_sync << '\n';
1004 if (!output_sync_macro.empty())
1005 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1006 os << "\\bibtex_command " << bibtex_command << '\n';
1007 os << "\\index_command " << index_command << '\n';
1009 if (!float_placement.empty()) {
1010 os << "\\float_placement " << float_placement << '\n';
1012 os << "\\paperfontsize " << fontsize << '\n';
1014 spacing().writeFile(os);
1015 pdfoptions().writeFile(os);
1017 os << "\\papersize " << string_papersize[papersize]
1018 << "\n\\use_geometry " << convert<string>(use_geometry);
1019 vector<string> const & packages = auto_packages();
1020 for (size_t i = 0; i < packages.size(); ++i)
1021 os << "\n\\use_package " << packages[i] << ' '
1022 << use_package(packages[i]);
1024 os << "\n\\cite_engine ";
1026 if (!cite_engine_.empty()) {
1027 LayoutModuleList::const_iterator be = cite_engine_.begin();
1028 LayoutModuleList::const_iterator en = cite_engine_.end();
1029 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1038 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1039 << "\n\\biblio_style " << biblio_style
1040 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1041 << "\n\\use_indices " << convert<string>(use_indices)
1042 << "\n\\paperorientation " << string_orientation[orientation]
1043 << "\n\\suppress_date " << convert<string>(suppress_date)
1044 << "\n\\justification " << convert<string>(justification)
1045 << "\n\\use_refstyle " << use_refstyle
1047 if (isbackgroundcolor == true)
1048 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1049 if (isfontcolor == true)
1050 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1051 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1052 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1053 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1054 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1056 BranchList::const_iterator it = branchlist().begin();
1057 BranchList::const_iterator end = branchlist().end();
1058 for (; it != end; ++it) {
1059 os << "\\branch " << to_utf8(it->branch())
1060 << "\n\\selected " << it->isSelected()
1061 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1062 << "\n\\color " << lyx::X11hexname(it->color())
1067 IndicesList::const_iterator iit = indiceslist().begin();
1068 IndicesList::const_iterator iend = indiceslist().end();
1069 for (; iit != iend; ++iit) {
1070 os << "\\index " << to_utf8(iit->index())
1071 << "\n\\shortcut " << to_utf8(iit->shortcut())
1072 << "\n\\color " << lyx::X11hexname(iit->color())
1077 if (!paperwidth.empty())
1078 os << "\\paperwidth "
1079 << VSpace(paperwidth).asLyXCommand() << '\n';
1080 if (!paperheight.empty())
1081 os << "\\paperheight "
1082 << VSpace(paperheight).asLyXCommand() << '\n';
1083 if (!leftmargin.empty())
1084 os << "\\leftmargin "
1085 << VSpace(leftmargin).asLyXCommand() << '\n';
1086 if (!topmargin.empty())
1087 os << "\\topmargin "
1088 << VSpace(topmargin).asLyXCommand() << '\n';
1089 if (!rightmargin.empty())
1090 os << "\\rightmargin "
1091 << VSpace(rightmargin).asLyXCommand() << '\n';
1092 if (!bottommargin.empty())
1093 os << "\\bottommargin "
1094 << VSpace(bottommargin).asLyXCommand() << '\n';
1095 if (!headheight.empty())
1096 os << "\\headheight "
1097 << VSpace(headheight).asLyXCommand() << '\n';
1098 if (!headsep.empty())
1100 << VSpace(headsep).asLyXCommand() << '\n';
1101 if (!footskip.empty())
1103 << VSpace(footskip).asLyXCommand() << '\n';
1104 if (!columnsep.empty())
1105 os << "\\columnsep "
1106 << VSpace(columnsep).asLyXCommand() << '\n';
1107 os << "\\secnumdepth " << secnumdepth
1108 << "\n\\tocdepth " << tocdepth
1109 << "\n\\paragraph_separation "
1110 << string_paragraph_separation[paragraph_separation];
1111 if (!paragraph_separation)
1112 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1114 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1115 os << "\n\\quotes_language "
1116 << string_quotes_language[quotes_language]
1117 << "\n\\papercolumns " << columns
1118 << "\n\\papersides " << sides
1119 << "\n\\paperpagestyle " << pagestyle << '\n';
1120 if (!listings_params.empty())
1121 os << "\\listings_params \"" <<
1122 InsetListingsParams(listings_params).encodedString() << "\"\n";
1123 for (int i = 0; i < 4; ++i) {
1124 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1125 if (user_defined_bullet(i).getFont() != -1) {
1126 os << "\\bullet " << i << " "
1127 << user_defined_bullet(i).getFont() << " "
1128 << user_defined_bullet(i).getCharacter() << " "
1129 << user_defined_bullet(i).getSize() << "\n";
1133 os << "\\bulletLaTeX " << i << " \""
1134 << lyx::to_ascii(user_defined_bullet(i).getText())
1140 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1141 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1142 << "\\html_math_output " << html_math_output << '\n'
1143 << "\\html_css_as_file " << html_css_as_file << '\n'
1144 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1146 if (html_math_img_scale != 1.0)
1147 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1148 if (!html_latex_start.empty())
1149 os << "\\html_latex_start " << html_latex_start << '\n';
1150 if (!html_latex_end.empty())
1151 os << "\\html_latex_end " << html_latex_end << '\n';
1153 os << pimpl_->authorlist;
1157 void BufferParams::validate(LaTeXFeatures & features) const
1159 features.require(documentClass().requires());
1161 if (outputChanges) {
1162 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1163 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1164 LaTeXFeatures::isAvailable("xcolor");
1166 switch (features.runparams().flavor) {
1167 case OutputParams::LATEX:
1168 case OutputParams::DVILUATEX:
1170 features.require("ct-dvipost");
1171 features.require("dvipost");
1172 } else if (xcolorulem) {
1173 features.require("ct-xcolor-ulem");
1174 features.require("ulem");
1175 features.require("xcolor");
1177 features.require("ct-none");
1180 case OutputParams::LUATEX:
1181 case OutputParams::PDFLATEX:
1182 case OutputParams::XETEX:
1184 features.require("ct-xcolor-ulem");
1185 features.require("ulem");
1186 features.require("xcolor");
1187 // improves color handling in PDF output
1188 features.require("pdfcolmk");
1190 features.require("ct-none");
1198 // Floats with 'Here definitely' as default setting.
1199 if (float_placement.find('H') != string::npos)
1200 features.require("float");
1202 for (PackageMap::const_iterator it = use_packages.begin();
1203 it != use_packages.end(); ++it) {
1204 if (it->first == "amsmath") {
1205 // AMS Style is at document level
1206 if (it->second == package_on ||
1207 features.isProvided("amsmath"))
1208 features.require(it->first);
1209 } else if (it->second == package_on)
1210 features.require(it->first);
1213 // Document-level line spacing
1214 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1215 features.require("setspace");
1217 // the bullet shapes are buffer level not paragraph level
1218 // so they are tested here
1219 for (int i = 0; i < 4; ++i) {
1220 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1222 int const font = user_defined_bullet(i).getFont();
1224 int const c = user_defined_bullet(i).getCharacter();
1230 features.require("latexsym");
1232 } else if (font == 1) {
1233 features.require("amssymb");
1234 } else if (font >= 2 && font <= 5) {
1235 features.require("pifont");
1239 if (pdfoptions().use_hyperref) {
1240 features.require("hyperref");
1241 // due to interferences with babel and hyperref, the color package has to
1242 // be loaded after hyperref when hyperref is used with the colorlinks
1243 // option, see http://www.lyx.org/trac/ticket/5291
1244 if (pdfoptions().colorlinks)
1245 features.require("color");
1248 // some languages are only available via polyglossia
1249 if (features.runparams().flavor == OutputParams::XETEX
1250 && (features.hasPolyglossiaExclusiveLanguages()
1252 features.require("polyglossia");
1254 if (!language->requires().empty())
1255 features.require(language->requires());
1259 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1260 FileName const & filepath) const
1262 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1263 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1264 // \RequirePackage to do so, rather than the normal \usepackage
1265 // Do not try to load any other package before the document class, unless you
1266 // have a thorough understanding of the LATEX internals and know exactly what you
1268 if (features.mustProvide("fix-cm"))
1269 os << "\\RequirePackage{fix-cm}\n";
1271 os << "\\documentclass";
1273 DocumentClass const & tclass = documentClass();
1275 ostringstream clsoptions; // the document class options.
1277 if (tokenPos(tclass.opt_fontsize(),
1278 '|', fontsize) >= 0) {
1279 // only write if existing in list (and not default)
1280 clsoptions << fontsize << "pt,";
1283 // all paper sizes except of A4, A5, B5 and the US sizes need the
1285 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1286 && papersize != PAPER_USLETTER
1287 && papersize != PAPER_USLEGAL
1288 && papersize != PAPER_USEXECUTIVE
1289 && papersize != PAPER_A4
1290 && papersize != PAPER_A5
1291 && papersize != PAPER_B5;
1293 if (!use_geometry) {
1294 switch (papersize) {
1296 clsoptions << "a4paper,";
1298 case PAPER_USLETTER:
1299 clsoptions << "letterpaper,";
1302 clsoptions << "a5paper,";
1305 clsoptions << "b5paper,";
1307 case PAPER_USEXECUTIVE:
1308 clsoptions << "executivepaper,";
1311 clsoptions << "legalpaper,";
1345 if (sides != tclass.sides()) {
1348 clsoptions << "oneside,";
1351 clsoptions << "twoside,";
1357 if (columns != tclass.columns()) {
1359 clsoptions << "twocolumn,";
1361 clsoptions << "onecolumn,";
1365 && orientation == ORIENTATION_LANDSCAPE)
1366 clsoptions << "landscape,";
1368 // language should be a parameter to \documentclass
1369 if (language->babel() == "hebrew"
1370 && default_language->babel() != "hebrew")
1371 // This seems necessary
1372 features.useLanguage(default_language);
1374 ostringstream language_options;
1375 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1376 bool const use_polyglossia = features.usePolyglossia();
1377 bool const global = lyxrc.language_global_options;
1378 if (use_babel || (use_polyglossia && global)) {
1379 language_options << features.getBabelLanguages();
1380 if (!language->babel().empty()) {
1381 if (!language_options.str().empty())
1382 language_options << ',';
1383 language_options << language->babel();
1385 if (global && !features.needBabelLangOptions()
1386 && !language_options.str().empty())
1387 clsoptions << language_options.str() << ',';
1390 // the predefined options from the layout
1391 if (use_default_options && !tclass.options().empty())
1392 clsoptions << tclass.options() << ',';
1394 // the user-defined options
1395 if (!options.empty()) {
1396 clsoptions << options << ',';
1399 string strOptions(clsoptions.str());
1400 if (!strOptions.empty()) {
1401 strOptions = rtrim(strOptions, ",");
1403 os << '[' << from_utf8(strOptions) << ']';
1406 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1407 // end of \documentclass defs
1409 // if we use fontspec, we have to load the AMS packages here
1410 string const ams = features.loadAMSPackages();
1411 if (useNonTeXFonts && !ams.empty())
1412 os << from_ascii(ams);
1415 os << "\\usepackage{fontspec}\n";
1417 // font selection must be done before loading fontenc.sty
1418 string const fonts = loadFonts(features);
1420 os << from_utf8(fonts);
1422 if (fonts_default_family != "default")
1423 os << "\\renewcommand{\\familydefault}{\\"
1424 << from_ascii(fonts_default_family) << "}\n";
1426 // set font encoding
1427 // for arabic_arabi and farsi we also need to load the LAE and
1429 // XeTeX and LuaTeX (with OS fonts) work without fontenc
1430 if (font_encoding() != "default" && language->lang() != "japanese"
1431 && !useNonTeXFonts && !features.isProvided("fontenc")) {
1432 size_t fars = language_options.str().find("farsi");
1433 size_t arab = language_options.str().find("arabic");
1434 if (language->lang() == "arabic_arabi"
1435 || language->lang() == "farsi" || fars != string::npos
1436 || arab != string::npos) {
1437 os << "\\usepackage[" << from_ascii(font_encoding())
1438 << ",LFE,LAE]{fontenc}\n";
1440 os << "\\usepackage[" << from_ascii(font_encoding())
1445 // handle inputenc etc.
1446 writeEncodingPreamble(os, features);
1449 if (!features.runparams().includeall && !included_children_.empty()) {
1450 os << "\\includeonly{";
1451 list<string>::const_iterator it = included_children_.begin();
1452 list<string>::const_iterator en = included_children_.end();
1454 for (; it != en; ++it) {
1455 string incfile = *it;
1456 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1457 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1459 if (!features.runparams().nice)
1461 // \includeonly doesn't want an extension
1462 incfile = changeExtension(incfile, string());
1463 incfile = support::latex_path(incfile);
1464 if (!incfile.empty()) {
1467 os << from_utf8(incfile);
1474 if (!listings_params.empty() || features.isRequired("listings"))
1475 os << "\\usepackage{listings}\n";
1477 if (!listings_params.empty()) {
1479 // do not test validity because listings_params is
1480 // supposed to be valid
1482 InsetListingsParams(listings_params).separatedParams(true);
1483 // we can't support all packages, but we should load the color package
1484 if (par.find("\\color", 0) != string::npos)
1485 features.require("color");
1486 os << from_utf8(par)
1489 if (!features.isProvided("geometry")
1490 && (use_geometry || nonstandard_papersize)) {
1491 odocstringstream ods;
1492 if (!getGraphicsDriver("geometry").empty())
1493 ods << getGraphicsDriver("geometry");
1494 if (orientation == ORIENTATION_LANDSCAPE)
1495 ods << ",landscape";
1496 switch (papersize) {
1498 if (!paperwidth.empty())
1499 ods << ",paperwidth="
1500 << from_ascii(paperwidth);
1501 if (!paperheight.empty())
1502 ods << ",paperheight="
1503 << from_ascii(paperheight);
1505 case PAPER_USLETTER:
1506 ods << ",letterpaper";
1509 ods << ",legalpaper";
1511 case PAPER_USEXECUTIVE:
1512 ods << ",executivepaper";
1601 docstring const g_options = trim(ods.str(), ",");
1602 os << "\\usepackage";
1603 if (!g_options.empty())
1604 os << '[' << g_options << ']';
1605 os << "{geometry}\n";
1606 // output this only if use_geometry is true
1608 os << "\\geometry{verbose";
1609 if (!topmargin.empty())
1610 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1611 if (!bottommargin.empty())
1612 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1613 if (!leftmargin.empty())
1614 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1615 if (!rightmargin.empty())
1616 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1617 if (!headheight.empty())
1618 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1619 if (!headsep.empty())
1620 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1621 if (!footskip.empty())
1622 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1623 if (!columnsep.empty())
1624 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1627 } else if (orientation == ORIENTATION_LANDSCAPE
1628 || papersize != PAPER_DEFAULT) {
1629 features.require("papersize");
1632 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1633 if (pagestyle == "fancy")
1634 os << "\\usepackage{fancyhdr}\n";
1635 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1638 // only output when the background color is not default
1639 if (isbackgroundcolor == true) {
1640 // only require color here, the background color will be defined
1641 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1643 features.require("color");
1644 features.require("pagecolor");
1647 // only output when the font color is not default
1648 if (isfontcolor == true) {
1649 // only require color here, the font color will be defined
1650 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1652 features.require("color");
1653 features.require("fontcolor");
1656 // Only if class has a ToC hierarchy
1657 if (tclass.hasTocLevels()) {
1658 if (secnumdepth != tclass.secnumdepth()) {
1659 os << "\\setcounter{secnumdepth}{"
1663 if (tocdepth != tclass.tocdepth()) {
1664 os << "\\setcounter{tocdepth}{"
1670 if (paragraph_separation) {
1671 // when skip separation
1672 switch (getDefSkip().kind()) {
1673 case VSpace::SMALLSKIP:
1674 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1676 case VSpace::MEDSKIP:
1677 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1679 case VSpace::BIGSKIP:
1680 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1682 case VSpace::LENGTH:
1683 os << "\\setlength{\\parskip}{"
1684 << from_utf8(getDefSkip().length().asLatexString())
1687 default: // should never happen // Then delete it.
1688 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1691 os << "\\setlength{\\parindent}{0pt}\n";
1693 // when separation by indentation
1694 // only output something when a width is given
1695 if (getIndentation().asLyXCommand() != "default") {
1696 os << "\\setlength{\\parindent}{"
1697 << from_utf8(getIndentation().asLatexCommand())
1702 // Now insert the LyX specific LaTeX commands...
1703 docstring lyxpreamble;
1704 features.resolveAlternatives();
1707 if (!output_sync_macro.empty())
1708 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1709 else if (features.runparams().flavor == OutputParams::LATEX)
1710 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1711 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1712 lyxpreamble += "\\synctex=-1\n";
1715 // due to interferences with babel and hyperref, the color package has to
1716 // be loaded (when it is not already loaded) before babel when hyperref
1717 // is used with the colorlinks option, see
1718 // http://www.lyx.org/trac/ticket/5291
1719 // we decided therefore to load color always before babel, see
1720 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1721 lyxpreamble += from_ascii(features.getColorOptions());
1723 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1725 && (features.isRequired("jurabib")
1726 || features.isRequired("hyperref")
1727 || features.isRequired("vietnamese")
1728 || features.isRequired("japanese"))) {
1730 lyxpreamble += from_utf8(features.getBabelPresettings());
1731 lyxpreamble += from_utf8(babelCall(language_options.str(),
1732 features.needBabelLangOptions())) + '\n';
1733 lyxpreamble += from_utf8(features.getBabelPostsettings());
1736 // The optional packages;
1737 lyxpreamble += from_ascii(features.getPackages());
1739 // Additional Indices
1740 if (features.isRequired("splitidx")) {
1741 IndicesList::const_iterator iit = indiceslist().begin();
1742 IndicesList::const_iterator iend = indiceslist().end();
1743 for (; iit != iend; ++iit) {
1744 pair<docstring, docstring> indexname_latex =
1745 features.runparams().encoding->latexString(iit->index(),
1746 features.runparams().dryrun);
1747 if (!indexname_latex.second.empty()) {
1748 // issue a warning about omitted characters
1749 // FIXME: should be passed to the error dialog
1750 frontend::Alert::warning(_("Uncodable characters"),
1751 bformat(_("The following characters that are used in an index name are not\n"
1752 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1753 indexname_latex.second));
1755 lyxpreamble += "\\newindex[";
1756 lyxpreamble += indexname_latex.first;
1757 lyxpreamble += "]{";
1758 lyxpreamble += escape(iit->shortcut());
1759 lyxpreamble += "}\n";
1764 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1767 // * Hyperref manual: "Make sure it comes last of your loaded
1768 // packages, to give it a fighting chance of not being over-written,
1769 // since its job is to redefine many LaTeX commands."
1770 // * Email from Heiko Oberdiek: "It is usually better to load babel
1771 // before hyperref. Then hyperref has a chance to detect babel.
1772 // * Has to be loaded before the "LyX specific LaTeX commands" to
1773 // avoid errors with algorithm floats.
1774 // use hyperref explicitly if it is required
1775 if (features.isRequired("hyperref")) {
1776 // pass what we have to stream here, since we need
1777 // to access the stream itself in PDFOptions.
1780 OutputParams tmp_params = features.runparams();
1781 pdfoptions().writeLaTeX(tmp_params, os,
1782 features.isProvided("hyperref"));
1783 // set back for the rest
1784 lyxpreamble.clear();
1785 // correctly break URLs with hyperref and dvi output
1786 if (features.runparams().flavor == OutputParams::LATEX
1787 && features.isAvailable("breakurl"))
1788 lyxpreamble += "\\usepackage{breakurl}\n";
1789 } else if (features.isRequired("nameref"))
1790 // hyperref loads this automatically
1791 lyxpreamble += "\\usepackage{nameref}\n";
1793 // bibtopic needs to be loaded after hyperref.
1794 // the dot provides the aux file naming which LyX can detect.
1795 if (features.mustProvide("bibtopic"))
1796 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1798 // Will be surrounded by \makeatletter and \makeatother when not empty
1799 docstring atlyxpreamble;
1801 // Some macros LyX will need
1802 docstring tmppreamble(features.getMacros());
1804 if (!tmppreamble.empty())
1805 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1806 "LyX specific LaTeX commands.\n"
1807 + tmppreamble + '\n';
1809 // the text class specific preamble
1810 tmppreamble = features.getTClassPreamble();
1811 if (!tmppreamble.empty())
1812 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1813 "Textclass specific LaTeX commands.\n"
1814 + tmppreamble + '\n';
1816 // suppress date if selected
1817 // use \@ifundefined because we cannot be sure that every document class
1818 // has a \date command
1820 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1822 /* the user-defined preamble */
1823 if (!containsOnly(preamble, " \n\t"))
1825 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1826 "User specified LaTeX commands.\n"
1827 + from_utf8(preamble) + '\n';
1829 // subfig loads internally the LaTeX package "caption". As
1830 // caption is a very popular package, users will load it in
1831 // the preamble. Therefore we must load subfig behind the
1832 // user-defined preamble and check if the caption package was
1833 // loaded or not. For the case that caption is loaded before
1834 // subfig, there is the subfig option "caption=false". This
1835 // option also works when a koma-script class is used and
1836 // koma's own caption commands are used instead of caption. We
1837 // use \PassOptionsToPackage here because the user could have
1838 // already loaded subfig in the preamble.
1839 if (features.isRequired("subfig")) {
1840 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1841 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1842 "\\usepackage{subfig}\n";
1845 // Itemize bullet settings need to be last in case the user
1846 // defines their own bullets that use a package included
1847 // in the user-defined preamble -- ARRae
1848 // Actually it has to be done much later than that
1849 // since some packages like frenchb make modifications
1850 // at \begin{document} time -- JMarc
1851 docstring bullets_def;
1852 for (int i = 0; i < 4; ++i) {
1853 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1854 if (bullets_def.empty())
1855 bullets_def += "\\AtBeginDocument{\n";
1856 bullets_def += " \\def\\labelitemi";
1858 // `i' is one less than the item to modify
1865 bullets_def += "ii";
1871 bullets_def += '{' +
1872 user_defined_bullet(i).getText()
1877 if (!bullets_def.empty())
1878 atlyxpreamble += bullets_def + "}\n\n";
1880 if (!atlyxpreamble.empty())
1881 lyxpreamble += "\n\\makeatletter\n"
1882 + atlyxpreamble + "\\makeatother\n\n";
1884 // We try to load babel late, in case it interferes with other packages.
1885 // Jurabib and Hyperref have to be called after babel, though.
1886 if (use_babel && !features.isRequired("jurabib")
1887 && !features.isRequired("hyperref")
1888 && !features.isRequired("vietnamese")
1889 && !features.isRequired("japanese")) {
1891 lyxpreamble += from_utf8(features.getBabelPresettings());
1892 lyxpreamble += from_utf8(babelCall(language_options.str(),
1893 features.needBabelLangOptions())) + '\n';
1894 lyxpreamble += from_utf8(features.getBabelPostsettings());
1897 // xunicode needs to be loaded at least after amsmath, amssymb,
1898 // esint and the other packages that provide special glyphs
1899 if (features.runparams().flavor == OutputParams::XETEX)
1900 lyxpreamble += "\\usepackage{xunicode}\n";
1902 // Polyglossia must be loaded last
1903 if (use_polyglossia) {
1905 lyxpreamble += "\\usepackage{polyglossia}\n";
1906 // set the main language
1907 lyxpreamble += "\\setdefaultlanguage";
1908 if (!language->polyglossiaOpts().empty())
1909 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1910 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1911 // now setup the other languages
1912 std::map<std::string, std::string> const polylangs =
1913 features.getPolyglossiaLanguages();
1914 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1915 mit != polylangs.end() ; ++mit) {
1916 lyxpreamble += "\\setotherlanguage";
1917 if (!mit->second.empty())
1918 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1919 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
1923 // Load custom language package here
1924 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
1925 if (lang_package == "default")
1926 lyxpreamble += from_utf8(lyxrc.language_custom_package);
1928 lyxpreamble += from_utf8(lang_package);
1929 lyxpreamble += '\n';
1932 docstring const i18npreamble =
1933 features.getTClassI18nPreamble(use_babel, use_polyglossia);
1934 if (!i18npreamble.empty())
1935 lyxpreamble += i18npreamble + '\n';
1943 void BufferParams::useClassDefaults()
1945 DocumentClass const & tclass = documentClass();
1947 sides = tclass.sides();
1948 columns = tclass.columns();
1949 pagestyle = tclass.pagestyle();
1950 use_default_options = true;
1951 // Only if class has a ToC hierarchy
1952 if (tclass.hasTocLevels()) {
1953 secnumdepth = tclass.secnumdepth();
1954 tocdepth = tclass.tocdepth();
1959 bool BufferParams::hasClassDefaults() const
1961 DocumentClass const & tclass = documentClass();
1963 return sides == tclass.sides()
1964 && columns == tclass.columns()
1965 && pagestyle == tclass.pagestyle()
1966 && use_default_options
1967 && secnumdepth == tclass.secnumdepth()
1968 && tocdepth == tclass.tocdepth();
1972 DocumentClass const & BufferParams::documentClass() const
1974 return *doc_class_.get();
1978 DocumentClassConstPtr BufferParams::documentClassPtr() const
1984 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
1986 // evil, but this function is evil
1987 doc_class_ = const_pointer_cast<DocumentClass>(tc);
1991 bool BufferParams::setBaseClass(string const & classname)
1993 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1994 LayoutFileList & bcl = LayoutFileList::get();
1995 if (!bcl.haveClass(classname)) {
1997 bformat(_("The layout file:\n"
1999 "could not be found. A default textclass with default\n"
2000 "layouts will be used. LyX will not be able to produce\n"
2002 from_utf8(classname));
2003 frontend::Alert::error(_("Document class not found"), s);
2004 bcl.addEmptyClass(classname);
2007 bool const success = bcl[classname].load();
2010 bformat(_("Due to some error in it, the layout file:\n"
2012 "could not be loaded. A default textclass with default\n"
2013 "layouts will be used. LyX will not be able to produce\n"
2015 from_utf8(classname));
2016 frontend::Alert::error(_("Could not load class"), s);
2017 bcl.addEmptyClass(classname);
2020 pimpl_->baseClass_ = classname;
2021 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2026 LayoutFile const * BufferParams::baseClass() const
2028 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2029 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2035 LayoutFileIndex const & BufferParams::baseClassID() const
2037 return pimpl_->baseClass_;
2041 void BufferParams::makeDocumentClass()
2046 LayoutModuleList mods;
2047 LayoutModuleList::iterator it;
2048 LayoutModuleList::iterator en;
2050 it = layout_modules_.begin();
2051 en = layout_modules_.end();
2052 for (; it != en; ++it)
2053 mods.push_back(*it);
2054 it = cite_engine_.begin();
2055 en = cite_engine_.end();
2056 for (; it != en; ++it)
2057 mods.push_back(*it);
2058 doc_class_ = getDocumentClass(*baseClass(), mods);
2060 if (!local_layout.empty()) {
2061 TextClass::ReturnValues success =
2062 doc_class_->read(local_layout, TextClass::MODULE);
2063 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2064 docstring const msg = _("Error reading internal layout information");
2065 frontend::Alert::warning(_("Read Error"), msg);
2071 bool BufferParams::moduleCanBeAdded(string const & modName) const
2073 return cite_engine_.moduleCanBeAdded(modName, baseClass()) &&
2074 layout_modules_.moduleCanBeAdded(modName, baseClass());
2078 bool BufferParams::addLayoutModule(string const & modName)
2080 LayoutModuleList::const_iterator it = layout_modules_.begin();
2081 LayoutModuleList::const_iterator end = layout_modules_.end();
2082 for (; it != end; ++it)
2085 layout_modules_.push_back(modName);
2090 string BufferParams::bufferFormat() const
2092 string format = documentClass().outputFormat();
2093 if (format == "latex") {
2096 if (encoding().package() == Encoding::japanese)
2103 bool BufferParams::isExportable(string const & format) const
2105 vector<string> backs = backends();
2106 for (vector<string>::const_iterator it = backs.begin();
2107 it != backs.end(); ++it)
2108 if (theConverters().isReachable(*it, format))
2115 bool formatSorter(Format const * lhs, Format const * rhs) {
2116 return _(lhs->prettyname()) < _(rhs->prettyname());
2121 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2123 vector<string> const backs = backends();
2124 set<string> excludes;
2125 if (useNonTeXFonts) {
2126 excludes.insert("latex");
2127 excludes.insert("pdflatex");
2129 vector<Format const *> result =
2130 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2131 for (vector<string>::const_iterator it = backs.begin() + 1;
2132 it != backs.end(); ++it) {
2133 vector<Format const *> r =
2134 theConverters().getReachable(*it, only_viewable, false, excludes);
2135 result.insert(result.end(), r.begin(), r.end());
2137 sort(result.begin(), result.end(), formatSorter);
2142 bool BufferParams::isExportableFormat(string const & format) const
2144 typedef vector<Format const *> Formats;
2146 formats = exportableFormats(true);
2147 Formats::const_iterator fit = formats.begin();
2148 Formats::const_iterator end = formats.end();
2149 for (; fit != end ; ++fit) {
2150 if ((*fit)->name() == format)
2157 vector<string> BufferParams::backends() const
2160 string const buffmt = bufferFormat();
2162 // FIXME: Don't hardcode format names here, but use a flag
2163 if (buffmt == "latex") {
2164 if (!useNonTeXFonts) {
2165 v.push_back("pdflatex");
2166 v.push_back("latex");
2168 v.push_back("luatex");
2169 v.push_back("dviluatex");
2170 v.push_back("xetex");
2171 } else if (buffmt == "xetex") {
2172 v.push_back("xetex");
2173 v.push_back("luatex");
2174 v.push_back("dviluatex");
2176 v.push_back(buffmt);
2178 v.push_back("xhtml");
2179 v.push_back("text");
2185 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const format) const
2187 string const dformat = (format.empty() || format == "default") ?
2188 getDefaultOutputFormat() : format;
2189 DefaultFlavorCache::const_iterator it =
2190 default_flavors_.find(dformat);
2192 if (it != default_flavors_.end())
2195 OutputParams::FLAVOR result = OutputParams::LATEX;
2197 // FIXME It'd be better not to hardcode this, but to do
2198 // something with formats.
2199 if (dformat == "xhtml")
2200 result = OutputParams::HTML;
2201 else if (dformat == "text")
2202 result = OutputParams::TEXT;
2203 else if (dformat == "lyx")
2204 result = OutputParams::LYX;
2205 else if (dformat == "pdflatex")
2206 result = OutputParams::PDFLATEX;
2207 else if (dformat == "xetex")
2208 result = OutputParams::XETEX;
2209 else if (dformat == "luatex")
2210 result = OutputParams::LUATEX;
2211 else if (dformat == "dviluatex")
2212 result = OutputParams::DVILUATEX;
2214 // Try to determine flavor of default output format
2215 vector<string> backs = backends();
2216 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2217 // Get shortest path to format
2218 Graph::EdgePath path;
2219 for (vector<string>::const_iterator it = backs.begin();
2220 it != backs.end(); ++it) {
2221 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2222 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2227 result = theConverters().getFlavor(path);
2230 // cache this flavor
2231 default_flavors_[dformat] = result;
2236 string BufferParams::getDefaultOutputFormat() const
2238 if (!default_output_format.empty()
2239 && default_output_format != "default")
2240 return default_output_format;
2243 || encoding().package() == Encoding::japanese) {
2244 vector<Format const *> const formats = exportableFormats(true);
2245 if (formats.empty())
2247 // return the first we find
2248 return formats.front()->name();
2250 return lyxrc.default_view_format;
2253 Font const BufferParams::getFont() const
2255 FontInfo f = documentClass().defaultfont();
2256 if (fonts_default_family == "rmdefault")
2257 f.setFamily(ROMAN_FAMILY);
2258 else if (fonts_default_family == "sfdefault")
2259 f.setFamily(SANS_FAMILY);
2260 else if (fonts_default_family == "ttdefault")
2261 f.setFamily(TYPEWRITER_FAMILY);
2262 return Font(f, language);
2266 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const qs) const
2268 return quoteslangtranslator().find(qs);
2272 bool BufferParams::isLatex() const
2274 return documentClass().outputType() == LATEX;
2278 bool BufferParams::isLiterate() const
2280 return documentClass().outputType() == LITERATE;
2284 bool BufferParams::isDocBook() const
2286 return documentClass().outputType() == DOCBOOK;
2290 void BufferParams::readPreamble(Lexer & lex)
2292 if (lex.getString() != "\\begin_preamble")
2293 lyxerr << "Error (BufferParams::readPreamble):"
2294 "consistency check failed." << endl;
2296 preamble = lex.getLongString("\\end_preamble");
2300 void BufferParams::readLocalLayout(Lexer & lex)
2302 if (lex.getString() != "\\begin_local_layout")
2303 lyxerr << "Error (BufferParams::readLocalLayout):"
2304 "consistency check failed." << endl;
2306 local_layout = lex.getLongString("\\end_local_layout");
2310 bool BufferParams::setLanguage(string const & lang)
2312 Language const *new_language = languages.getLanguage(lang);
2313 if (!new_language) {
2314 // Language lang was not found
2317 language = new_language;
2322 void BufferParams::readLanguage(Lexer & lex)
2324 if (!lex.next()) return;
2326 string const tmptok = lex.getString();
2328 // check if tmptok is part of tex_babel in tex-defs.h
2329 if (!setLanguage(tmptok)) {
2330 // Language tmptok was not found
2331 language = default_language;
2332 lyxerr << "Warning: Setting language `"
2333 << tmptok << "' to `" << language->lang()
2339 void BufferParams::readGraphicsDriver(Lexer & lex)
2344 string const tmptok = lex.getString();
2345 // check if tmptok is part of tex_graphics in tex_defs.h
2348 string const test = tex_graphics[n++];
2350 if (test == tmptok) {
2351 graphics_driver = tmptok;
2356 "Warning: graphics driver `$$Token' not recognized!\n"
2357 " Setting graphics driver to `default'.\n");
2358 graphics_driver = "default";
2365 void BufferParams::readBullets(Lexer & lex)
2370 int const index = lex.getInteger();
2372 int temp_int = lex.getInteger();
2373 user_defined_bullet(index).setFont(temp_int);
2374 temp_bullet(index).setFont(temp_int);
2376 user_defined_bullet(index).setCharacter(temp_int);
2377 temp_bullet(index).setCharacter(temp_int);
2379 user_defined_bullet(index).setSize(temp_int);
2380 temp_bullet(index).setSize(temp_int);
2384 void BufferParams::readBulletsLaTeX(Lexer & lex)
2386 // The bullet class should be able to read this.
2389 int const index = lex.getInteger();
2391 docstring const temp_str = lex.getDocString();
2393 user_defined_bullet(index).setText(temp_str);
2394 temp_bullet(index).setText(temp_str);
2398 void BufferParams::readModules(Lexer & lex)
2400 if (!lex.eatLine()) {
2401 lyxerr << "Error (BufferParams::readModules):"
2402 "Unexpected end of input." << endl;
2406 string mod = lex.getString();
2407 if (mod == "\\end_modules")
2409 addLayoutModule(mod);
2415 void BufferParams::readRemovedModules(Lexer & lex)
2417 if (!lex.eatLine()) {
2418 lyxerr << "Error (BufferParams::readRemovedModules):"
2419 "Unexpected end of input." << endl;
2423 string mod = lex.getString();
2424 if (mod == "\\end_removed_modules")
2426 removed_modules_.push_back(mod);
2429 // now we want to remove any removed modules that were previously
2430 // added. normally, that will be because default modules were added in
2431 // setBaseClass(), which gets called when \textclass is read at the
2432 // start of the read.
2433 list<string>::const_iterator rit = removed_modules_.begin();
2434 list<string>::const_iterator const ren = removed_modules_.end();
2435 for (; rit != ren; ++rit) {
2436 LayoutModuleList::iterator const mit = layout_modules_.begin();
2437 LayoutModuleList::iterator const men = layout_modules_.end();
2438 LayoutModuleList::iterator found = find(mit, men, *rit);
2441 layout_modules_.erase(found);
2446 void BufferParams::readIncludeonly(Lexer & lex)
2448 if (!lex.eatLine()) {
2449 lyxerr << "Error (BufferParams::readIncludeonly):"
2450 "Unexpected end of input." << endl;
2454 string child = lex.getString();
2455 if (child == "\\end_includeonly")
2457 included_children_.push_back(child);
2463 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2465 switch (papersize) {
2467 // could be anything, so don't guess
2469 case PAPER_CUSTOM: {
2470 if (purpose == XDVI && !paperwidth.empty() &&
2471 !paperheight.empty()) {
2472 // heightxwidth<unit>
2473 string first = paperwidth;
2474 string second = paperheight;
2475 if (orientation == ORIENTATION_LANDSCAPE)
2478 return first.erase(first.length() - 2)
2484 // dvips and dvipdfm do not know this
2485 if (purpose == DVIPS || purpose == DVIPDFM)
2489 if (purpose == DVIPS || purpose == DVIPDFM)
2493 if (purpose == DVIPS || purpose == DVIPDFM)
2503 if (purpose == DVIPS || purpose == DVIPDFM)
2507 if (purpose == DVIPS || purpose == DVIPDFM)
2511 if (purpose == DVIPS || purpose == DVIPDFM)
2515 if (purpose == DVIPS || purpose == DVIPDFM)
2519 if (purpose == DVIPS || purpose == DVIPDFM)
2523 // dvipdfm does not know this
2524 if (purpose == DVIPDFM)
2528 if (purpose == DVIPDFM)
2532 if (purpose == DVIPS || purpose == DVIPDFM)
2536 if (purpose == DVIPS || purpose == DVIPDFM)
2540 if (purpose == DVIPS || purpose == DVIPDFM)
2544 if (purpose == DVIPS || purpose == DVIPDFM)
2548 if (purpose == DVIPS || purpose == DVIPDFM)
2552 if (purpose == DVIPS || purpose == DVIPDFM)
2556 if (purpose == DVIPS || purpose == DVIPDFM)
2560 if (purpose == DVIPS || purpose == DVIPDFM)
2564 if (purpose == DVIPS || purpose == DVIPDFM)
2568 if (purpose == DVIPS || purpose == DVIPDFM)
2572 if (purpose == DVIPS || purpose == DVIPDFM)
2576 if (purpose == DVIPS || purpose == DVIPDFM)
2580 if (purpose == DVIPS || purpose == DVIPDFM)
2584 if (purpose == DVIPS || purpose == DVIPDFM)
2588 if (purpose == DVIPS || purpose == DVIPDFM)
2591 case PAPER_USEXECUTIVE:
2592 // dvipdfm does not know this
2593 if (purpose == DVIPDFM)
2598 case PAPER_USLETTER:
2600 if (purpose == XDVI)
2607 string const BufferParams::dvips_options() const
2611 // If the class loads the geometry package, we do not know which
2612 // paper size is used, since we do not set it (bug 7013).
2613 // Therefore we must not specify any argument here.
2614 // dvips gets the correct paper size via DVI specials in this case
2615 // (if the class uses the geometry package correctly).
2616 if (documentClass().provides("geometry"))
2620 && papersize == PAPER_CUSTOM
2621 && !lyxrc.print_paper_dimension_flag.empty()
2622 && !paperwidth.empty()
2623 && !paperheight.empty()) {
2624 // using a custom papersize
2625 result = lyxrc.print_paper_dimension_flag;
2626 result += ' ' + paperwidth;
2627 result += ',' + paperheight;
2629 string const paper_option = paperSizeName(DVIPS);
2630 if (!paper_option.empty() && (paper_option != "letter" ||
2631 orientation != ORIENTATION_LANDSCAPE)) {
2632 // dvips won't accept -t letter -t landscape.
2633 // In all other cases, include the paper size
2635 result = lyxrc.print_paper_flag;
2636 result += ' ' + paper_option;
2639 if (orientation == ORIENTATION_LANDSCAPE &&
2640 papersize != PAPER_CUSTOM)
2641 result += ' ' + lyxrc.print_landscape_flag;
2646 string const BufferParams::font_encoding() const
2648 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2652 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2654 // suppress the babel call if there is no BabelName defined
2655 // for the document language in the lib/languages file and if no
2656 // other languages are used (lang_opts is then empty)
2657 if (lang_opts.empty())
2659 // either a specific language (AsBabelOptions setting in
2660 // lib/languages) or the prefs require the languages to
2661 // be submitted to babel itself (not the class).
2663 return "\\usepackage[" + lang_opts + "]{babel}";
2664 return "\\usepackage{babel}";
2668 docstring BufferParams::getGraphicsDriver(string const & package) const
2672 if (package == "geometry") {
2673 if (graphics_driver == "dvips"
2674 || graphics_driver == "dvipdfm"
2675 || graphics_driver == "pdftex"
2676 || graphics_driver == "vtex")
2677 result = from_ascii(graphics_driver);
2678 else if (graphics_driver == "dvipdfmx")
2679 result = from_ascii("dvipdfm");
2686 void BufferParams::writeEncodingPreamble(otexstream & os,
2687 LaTeXFeatures & features) const
2689 // XeTeX does not need this
2690 if (features.runparams().flavor == OutputParams::XETEX)
2692 // LuaTeX neither, but with tex fonts, we need to load
2693 // the luainputenc package.
2694 if (features.runparams().flavor == OutputParams::LUATEX
2695 || features.runparams().flavor == OutputParams::DVILUATEX) {
2696 if (!useNonTeXFonts && inputenc != "default"
2697 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2698 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2699 os << "\\usepackage[utf8]{luainputenc}\n";
2703 if (inputenc == "auto") {
2704 string const doc_encoding =
2705 language->encoding()->latexName();
2706 Encoding::Package const package =
2707 language->encoding()->package();
2709 // Create a list with all the input encodings used
2711 set<string> encodings =
2712 features.getEncodingSet(doc_encoding);
2714 // If the "japanese" package (i.e. pLaTeX) is used,
2715 // inputenc must be omitted.
2716 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2717 if ((!encodings.empty() || package == Encoding::inputenc)
2718 && !features.isRequired("japanese")) {
2719 os << "\\usepackage[";
2720 set<string>::const_iterator it = encodings.begin();
2721 set<string>::const_iterator const end = encodings.end();
2723 os << from_ascii(*it);
2726 for (; it != end; ++it)
2727 os << ',' << from_ascii(*it);
2728 if (package == Encoding::inputenc) {
2729 if (!encodings.empty())
2731 os << from_ascii(doc_encoding);
2733 os << "]{inputenc}\n";
2735 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2736 if (language->encoding()->name() == "utf8-cjk"
2737 && LaTeXFeatures::isAvailable("CJKutf8"))
2738 os << "\\usepackage{CJKutf8}\n";
2740 os << "\\usepackage{CJK}\n";
2742 } else if (inputenc != "default") {
2743 switch (encoding().package()) {
2744 case Encoding::none:
2745 case Encoding::japanese:
2747 case Encoding::inputenc:
2748 // do not load inputenc if japanese is used
2749 if (features.isRequired("japanese"))
2751 os << "\\usepackage[" << from_ascii(inputenc)
2755 if (encoding().name() == "utf8-cjk"
2756 && LaTeXFeatures::isAvailable("CJKutf8"))
2757 os << "\\usepackage{CJKutf8}\n";
2759 os << "\\usepackage{CJK}\n";
2766 string const BufferParams::parseFontName(string const & name) const
2768 string mangled = name;
2769 size_t const idx = mangled.find('[');
2770 if (idx == string::npos || idx == 0)
2773 return mangled.substr(0, idx - 1);
2777 string const BufferParams::loadFonts(LaTeXFeatures & features) const
2779 // TODO: separate math fonts.
2781 if (fonts_roman == "default" && fonts_sans == "default"
2782 && fonts_typewriter == "default")
2788 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2789 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2790 * Mapping=tex-text option assures TeX ligatures (such as "--")
2791 * are resolved. Note that tt does not use these ligatures.
2793 * -- add more GUI options?
2794 * -- add more fonts (fonts for other scripts)
2795 * -- if there's a way to find out if a font really supports
2796 * OldStyle, enable/disable the widget accordingly.
2798 if (useNonTeXFonts && features.isAvailable("fontspec")) {
2799 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2800 // However, until v.2 (2010/07/11) fontspec only knew
2801 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2802 // was introduced for both XeTeX and LuaTeX (LuaTeX
2803 // didn't understand "Mapping=tex-text", while XeTeX
2804 // understood both. With most recent versions, both
2805 // variants are understood by both engines. However,
2806 // we want to provide support for at least TeXLive 2009
2807 // (for XeTeX; LuaTeX is only supported as of v.2)
2808 string const texmapping =
2809 (features.runparams().flavor == OutputParams::XETEX) ?
2810 "Mapping=tex-text" : "Ligatures=TeX";
2811 if (fonts_roman != "default") {
2812 os << "\\setmainfont[" << texmapping;
2813 if (fonts_old_figures)
2814 os << ",Numbers=OldStyle";
2815 os << "]{" << parseFontName(fonts_roman) << "}\n";
2817 if (fonts_sans != "default") {
2818 string const sans = parseFontName(fonts_sans);
2819 if (fonts_sans_scale != 100)
2820 os << "\\setsansfont[Scale="
2821 << float(fonts_sans_scale) / 100
2822 << "," << texmapping << "]{"
2825 os << "\\setsansfont[" << texmapping << "]{"
2828 if (fonts_typewriter != "default") {
2829 string const mono = parseFontName(fonts_typewriter);
2830 if (fonts_typewriter_scale != 100)
2831 os << "\\setmonofont[Scale="
2832 << float(fonts_typewriter_scale) / 100
2836 os << "\\setmonofont{"
2843 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
2844 bool const dryrun = features.runparams().dryrun;
2845 bool const complete = (fonts_sans == "default" && fonts_typewriter == "default");
2848 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_roman)).getLaTeXCode(
2849 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures);
2852 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_sans)).getLaTeXCode(
2853 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures, fonts_sans_scale);
2855 // MONOSPACED/TYPEWRITER
2856 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_typewriter)).getLaTeXCode(
2857 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures, fonts_typewriter_scale);
2863 Encoding const & BufferParams::encoding() const
2865 // FIXME: actually, we should check for the flavor
2866 // or runparams.isFullyUnicode() here:
2867 // This check will not work with XeTeX/LuaTeX and tex fonts.
2868 // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2870 return *(encodings.fromLaTeXName("utf8-plain"));
2871 if (inputenc == "auto" || inputenc == "default")
2872 return *language->encoding();
2873 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2876 LYXERR0("Unknown inputenc value `" << inputenc
2877 << "'. Using `auto' instead.");
2878 return *language->encoding();
2882 bool BufferParams::addCiteEngine(string const & engine)
2884 LayoutModuleList::const_iterator it = cite_engine_.begin();
2885 LayoutModuleList::const_iterator en = cite_engine_.end();
2886 for (; it != en; ++it)
2889 cite_engine_.push_back(engine);
2894 bool BufferParams::addCiteEngine(vector<string> const & engine)
2896 vector<string>::const_iterator it = engine.begin();
2897 vector<string>::const_iterator en = engine.end();
2899 for (; it != en; ++it)
2900 if (!addCiteEngine(*it))
2906 string const & BufferParams::defaultBiblioStyle() const
2908 return documentClass().defaultBiblioStyle();
2912 bool const & BufferParams::fullAuthorList() const
2914 return documentClass().fullAuthorList();
2918 void BufferParams::setCiteEngine(string const & engine)
2921 addCiteEngine(engine);
2925 void BufferParams::setCiteEngine(vector<string> const & engine)
2928 addCiteEngine(engine);
2932 vector<string> BufferParams::citeCommands() const
2934 static CitationStyle const default_style;
2935 vector<string> commands =
2936 documentClass().citeCommands(citeEngineType());
2937 if (commands.empty())
2938 commands.push_back(default_style.cmd);
2943 vector<CitationStyle> BufferParams::citeStyles() const
2945 static CitationStyle const default_style;
2946 vector<CitationStyle> styles =
2947 documentClass().citeStyles(citeEngineType());
2949 styles.push_back(default_style);