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"
24 #include "buffer_funcs.h"
26 #include "CiteEnginesList.h"
29 #include "Converter.h"
31 #include "IndicesList.h"
33 #include "LaTeXFeatures.h"
34 #include "LaTeXFonts.h"
36 #include "ModuleList.h"
40 #include "OutputParams.h"
42 #include "texstream.h"
45 #include "PDFOptions.h"
47 #include "frontends/alert.h"
49 #include "insets/InsetListingsParams.h"
51 #include "support/convert.h"
52 #include "support/debug.h"
53 #include "support/docstream.h"
54 #include "support/FileName.h"
55 #include "support/filetools.h"
56 #include "support/gettext.h"
57 #include "support/Messages.h"
58 #include "support/mutex.h"
59 #include "support/Package.h"
60 #include "support/Translator.h"
61 #include "support/lstrings.h"
67 using namespace lyx::support;
70 static char const * const string_paragraph_separation[] = {
75 static char const * const string_quotes_style[] = {
76 "english", "swedish", "german", "polish", "swiss", "danish", "plain",
77 "british", "swedishg", "french", "frenchin", "russian", "cjk", "cjkangle", ""
81 static char const * const string_papersize[] = {
82 "default", "custom", "letter", "legal", "executive",
83 "a0", "a1", "a2", "a3", "a4", "a5", "a6",
84 "b0", "b1", "b2", "b3", "b4", "b5", "b6",
85 "c0", "c1", "c2", "c3", "c4", "c5", "c6",
86 "b0j", "b1j", "b2j", "b3j", "b4j", "b5j", "b6j", ""
90 static char const * const string_papersize_geometry[] = {
91 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
92 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper", "a6paper",
93 "b0paper", "b1paper", "b2paper", "b3paper", "b4paper", "b5paper", "b6paper",
94 "c0paper", "c1paper", "c2paper", "c3paper", "c4paper", "c5paper", "c6paper",
95 "b0j", "b1j", "b2j", "b3j", "b4j", "b5j", "b6j", ""
99 static char const * const string_orientation[] = {
100 "portrait", "landscape", ""
104 static char const * const tex_graphics[] = {
105 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
106 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
107 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
108 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
118 // Paragraph separation
119 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
122 ParSepTranslator const init_parseptranslator()
124 ParSepTranslator translator
125 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
126 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
131 ParSepTranslator const & parseptranslator()
133 static ParSepTranslator const translator =
134 init_parseptranslator();
140 typedef Translator<string, InsetQuotesParams::QuoteStyle> QuotesStyleTranslator;
143 QuotesStyleTranslator const init_quotesstyletranslator()
145 QuotesStyleTranslator translator
146 (string_quotes_style[0], InsetQuotesParams::EnglishQuotes);
147 translator.addPair(string_quotes_style[1], InsetQuotesParams::SwedishQuotes);
148 translator.addPair(string_quotes_style[2], InsetQuotesParams::GermanQuotes);
149 translator.addPair(string_quotes_style[3], InsetQuotesParams::PolishQuotes);
150 translator.addPair(string_quotes_style[4], InsetQuotesParams::SwissQuotes);
151 translator.addPair(string_quotes_style[5], InsetQuotesParams::DanishQuotes);
152 translator.addPair(string_quotes_style[6], InsetQuotesParams::PlainQuotes);
153 translator.addPair(string_quotes_style[7], InsetQuotesParams::BritishQuotes);
154 translator.addPair(string_quotes_style[8], InsetQuotesParams::SwedishGQuotes);
155 translator.addPair(string_quotes_style[9], InsetQuotesParams::FrenchQuotes);
156 translator.addPair(string_quotes_style[10], InsetQuotesParams::FrenchINQuotes);
157 translator.addPair(string_quotes_style[11], InsetQuotesParams::RussianQuotes);
158 translator.addPair(string_quotes_style[12], InsetQuotesParams::CJKQuotes);
159 translator.addPair(string_quotes_style[13], InsetQuotesParams::CJKAngleQuotes);
164 QuotesStyleTranslator const & quotesstyletranslator()
166 static QuotesStyleTranslator const translator =
167 init_quotesstyletranslator();
173 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
176 static PaperSizeTranslator initPaperSizeTranslator()
178 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
179 translator.addPair(string_papersize[1], PAPER_CUSTOM);
180 translator.addPair(string_papersize[2], PAPER_USLETTER);
181 translator.addPair(string_papersize[3], PAPER_USLEGAL);
182 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
183 translator.addPair(string_papersize[5], PAPER_A0);
184 translator.addPair(string_papersize[6], PAPER_A1);
185 translator.addPair(string_papersize[7], PAPER_A2);
186 translator.addPair(string_papersize[8], PAPER_A3);
187 translator.addPair(string_papersize[9], PAPER_A4);
188 translator.addPair(string_papersize[10], PAPER_A5);
189 translator.addPair(string_papersize[11], PAPER_A6);
190 translator.addPair(string_papersize[12], PAPER_B0);
191 translator.addPair(string_papersize[13], PAPER_B1);
192 translator.addPair(string_papersize[14], PAPER_B2);
193 translator.addPair(string_papersize[15], PAPER_B3);
194 translator.addPair(string_papersize[16], PAPER_B4);
195 translator.addPair(string_papersize[17], PAPER_B5);
196 translator.addPair(string_papersize[18], PAPER_B6);
197 translator.addPair(string_papersize[19], PAPER_C0);
198 translator.addPair(string_papersize[20], PAPER_C1);
199 translator.addPair(string_papersize[21], PAPER_C2);
200 translator.addPair(string_papersize[22], PAPER_C3);
201 translator.addPair(string_papersize[23], PAPER_C4);
202 translator.addPair(string_papersize[24], PAPER_C5);
203 translator.addPair(string_papersize[25], PAPER_C6);
204 translator.addPair(string_papersize[26], PAPER_JISB0);
205 translator.addPair(string_papersize[27], PAPER_JISB1);
206 translator.addPair(string_papersize[28], PAPER_JISB2);
207 translator.addPair(string_papersize[29], PAPER_JISB3);
208 translator.addPair(string_papersize[30], PAPER_JISB4);
209 translator.addPair(string_papersize[31], PAPER_JISB5);
210 translator.addPair(string_papersize[32], PAPER_JISB6);
215 PaperSizeTranslator const & papersizetranslator()
217 static PaperSizeTranslator const translator =
218 initPaperSizeTranslator();
224 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
227 PaperOrientationTranslator const init_paperorientationtranslator()
229 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
230 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
235 PaperOrientationTranslator const & paperorientationtranslator()
237 static PaperOrientationTranslator const translator =
238 init_paperorientationtranslator();
244 typedef Translator<int, PageSides> SidesTranslator;
247 SidesTranslator const init_sidestranslator()
249 SidesTranslator translator(1, OneSide);
250 translator.addPair(2, TwoSides);
255 SidesTranslator const & sidestranslator()
257 static SidesTranslator const translator = init_sidestranslator();
263 typedef Translator<int, BufferParams::Package> PackageTranslator;
266 PackageTranslator const init_packagetranslator()
268 PackageTranslator translator(0, BufferParams::package_off);
269 translator.addPair(1, BufferParams::package_auto);
270 translator.addPair(2, BufferParams::package_on);
275 PackageTranslator const & packagetranslator()
277 static PackageTranslator const translator =
278 init_packagetranslator();
284 typedef Translator<string, Spacing::Space> SpaceTranslator;
287 SpaceTranslator const init_spacetranslator()
289 SpaceTranslator translator("default", Spacing::Default);
290 translator.addPair("single", Spacing::Single);
291 translator.addPair("onehalf", Spacing::Onehalf);
292 translator.addPair("double", Spacing::Double);
293 translator.addPair("other", Spacing::Other);
298 SpaceTranslator const & spacetranslator()
300 static SpaceTranslator const translator = init_spacetranslator();
305 bool inSystemDir(FileName const & document_dir, string & system_dir)
307 // A document is assumed to be in a system LyX directory (not
308 // necessarily the system directory of the running instance)
309 // if both "configure.py" and "chkconfig.ltx" are found in
310 // either document_dir/../ or document_dir/../../.
311 // If true, the system directory path is returned in system_dir
312 // with a trailing path separator.
314 string const msg = "Checking whether document is in a system dir...";
316 string dir = document_dir.absFileName();
318 for (int i = 0; i < 3; ++i) {
319 dir = addPath(dir, "..");
320 if (!fileSearch(dir, "configure.py").empty() &&
321 !fileSearch(dir, "chkconfig.ltx").empty()) {
322 LYXERR(Debug::FILES, msg << " yes");
323 system_dir = addPath(FileName(dir).realPath(), "");
328 LYXERR(Debug::FILES, msg << " no");
329 system_dir = string();
336 class BufferParams::Impl
341 AuthorList authorlist;
342 BranchList branchlist;
343 Bullet temp_bullets[4];
344 Bullet user_defined_bullets[4];
345 IndicesList indiceslist;
349 /** This is the amount of space used for paragraph_separation "skip",
350 * and for detached paragraphs in "indented" documents.
353 PDFOptions pdfoptions;
354 LayoutFileIndex baseClass_;
355 FormatList exportableFormatList;
356 FormatList viewableFormatList;
357 bool isViewCacheValid;
358 bool isExportCacheValid;
362 BufferParams::Impl::Impl()
363 : defskip(VSpace::MEDSKIP), baseClass_(string("")),
364 isViewCacheValid(false), isExportCacheValid(false)
366 // set initial author
368 authorlist.record(Author(from_utf8(lyxrc.user_name),
369 from_utf8(lyxrc.user_email),
370 from_utf8(lyxrc.user_initials)));
375 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
378 return new BufferParams::Impl(*ptr);
382 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
388 BufferParams::BufferParams()
391 setBaseClass(defaultBaseclass());
392 cite_engine_ = "basic";
393 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
395 paragraph_separation = ParagraphIndentSeparation;
396 is_math_indent = false;
397 math_numbering_side = DEFAULT;
398 quotes_style = InsetQuotesParams::EnglishQuotes;
399 dynamic_quotes = false;
400 fontsize = "default";
403 papersize = PAPER_DEFAULT;
404 orientation = ORIENTATION_PORTRAIT;
405 use_geometry = false;
406 biblio_style = string();
407 use_bibtopic = false;
410 save_transient_properties = true;
411 track_changes = false;
412 output_changes = false;
414 postpone_fragile_content = true;
415 use_default_options = true;
416 maintain_unincluded_children = CM_None;
419 language = default_language;
421 fonts_roman[0] = "default";
422 fonts_roman[1] = "default";
423 fonts_sans[0] = "default";
424 fonts_sans[1] = "default";
425 fonts_typewriter[0] = "default";
426 fonts_typewriter[1] = "default";
427 fonts_math[0] = "auto";
428 fonts_math[1] = "auto";
429 fonts_default_family = "default";
430 useNonTeXFonts = false;
431 use_microtype = false;
432 use_dash_ligatures = true;
433 fonts_expert_sc = false;
434 fonts_roman_osf = false;
435 fonts_sans_osf = false;
436 fonts_typewriter_osf = false;
437 fonts_sans_scale[0] = 100;
438 fonts_sans_scale[1] = 100;
439 fonts_typewriter_scale[0] = 100;
440 fonts_typewriter_scale[1] = 100;
442 lang_package = "default";
443 graphics_driver = "default";
444 default_output_format = "default";
445 bibtex_command = "default";
446 index_command = "default";
449 listings_params = string();
450 pagestyle = "default";
451 tablestyle = "default";
452 suppress_date = false;
453 justification = true;
454 // no color is the default (white)
455 backgroundcolor = lyx::rgbFromHexName("#ffffff");
456 isbackgroundcolor = false;
457 // no color is the default (black)
458 fontcolor = lyx::rgbFromHexName("#000000");
460 // light gray is the default font color for greyed-out notes
461 notefontcolor = lyx::rgbFromHexName("#cccccc");
462 boxbgcolor = lyx::rgbFromHexName("#ff0000");
463 compressed = lyxrc.save_compressed;
464 for (int iter = 0; iter < 4; ++iter) {
465 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
466 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
469 indiceslist().addDefault(B_("Index"));
470 html_be_strict = false;
471 html_math_output = MathML;
472 html_math_img_scale = 1.0;
473 html_css_as_file = false;
474 display_pixel_ratio = 1.0;
476 shell_escape = false;
482 // map current author
483 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
487 docstring BufferParams::B_(string const & l10n) const
489 LASSERT(language, return from_utf8(l10n));
490 return getMessages(language->code()).get(l10n);
494 BufferParams::Package BufferParams::use_package(std::string const & p) const
496 PackageMap::const_iterator it = use_packages.find(p);
497 if (it == use_packages.end())
503 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
509 map<string, string> const & BufferParams::auto_packages()
511 static map<string, string> packages;
512 if (packages.empty()) {
513 // We could have a race condition here that two threads
514 // discover an empty map at the same time and want to fill
515 // it, but that is no problem, since the same contents is
516 // filled in twice then. Having the locker inside the
517 // packages.empty() condition has the advantage that we
518 // don't need the mutex overhead for simple reading.
520 Mutex::Locker locker(&mutex);
521 // adding a package here implies a file format change!
522 packages["amsmath"] =
523 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
524 packages["amssymb"] =
525 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
527 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
529 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
530 packages["mathdots"] =
531 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
532 packages["mathtools"] =
533 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
535 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
536 packages["stackrel"] =
537 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
538 packages["stmaryrd"] =
539 N_("The LaTeX package stmaryrd is only used if symbols from the St Mary's Road symbol font for theoretical computer science are inserted into formulas");
540 packages["undertilde"] =
541 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
547 bool BufferParams::useBibtopic() const
551 return (use_bibtopic || (!multibib.empty() && multibib != "child"));
555 AuthorList & BufferParams::authors()
557 return pimpl_->authorlist;
561 AuthorList const & BufferParams::authors() const
563 return pimpl_->authorlist;
567 void BufferParams::addAuthor(Author a)
569 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
573 BranchList & BufferParams::branchlist()
575 return pimpl_->branchlist;
579 BranchList const & BufferParams::branchlist() const
581 return pimpl_->branchlist;
585 IndicesList & BufferParams::indiceslist()
587 return pimpl_->indiceslist;
591 IndicesList const & BufferParams::indiceslist() const
593 return pimpl_->indiceslist;
597 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
599 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
600 return pimpl_->temp_bullets[index];
604 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
606 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
607 return pimpl_->temp_bullets[index];
611 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
613 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
614 return pimpl_->user_defined_bullets[index];
618 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
620 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
621 return pimpl_->user_defined_bullets[index];
625 Spacing & BufferParams::spacing()
627 return pimpl_->spacing;
631 Spacing const & BufferParams::spacing() const
633 return pimpl_->spacing;
637 PDFOptions & BufferParams::pdfoptions()
639 return pimpl_->pdfoptions;
643 PDFOptions const & BufferParams::pdfoptions() const
645 return pimpl_->pdfoptions;
649 Length const & BufferParams::getMathIndent() const
651 return pimpl_->mathindent;
655 void BufferParams::setMathIndent(Length const & indent)
657 pimpl_->mathindent = indent;
661 Length const & BufferParams::getParIndent() const
663 return pimpl_->parindent;
667 void BufferParams::setParIndent(Length const & indent)
669 pimpl_->parindent = indent;
673 VSpace const & BufferParams::getDefSkip() const
675 return pimpl_->defskip;
679 void BufferParams::setDefSkip(VSpace const & vs)
681 // DEFSKIP will cause an infinite loop
682 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
683 pimpl_->defskip = vs;
687 BufferParams::MathNumber BufferParams::getMathNumber() const
689 if (math_numbering_side != DEFAULT)
690 return math_numbering_side;
691 // FIXME: do not hardcode language here
692 else if (language->lang() == "arabic_arabi"
693 || documentClass().provides("leqno"))
700 string BufferParams::readToken(Lexer & lex, string const & token,
701 FileName const & filepath)
705 if (token == "\\textclass") {
707 string const classname = lex.getString();
708 // if there exists a local layout file, ignore the system one
709 // NOTE: in this case, the textclass (.cls file) is assumed to
712 LayoutFileList & bcl = LayoutFileList::get();
713 if (!filepath.empty()) {
714 // If classname is an absolute path, the document is
715 // using a local layout file which could not be accessed
716 // by a relative path. In this case the path is correct
717 // even if the document was moved to a different
718 // location. However, we will have a problem if the
719 // document was generated on a different platform.
720 bool isabsolute = FileName::isAbsolute(classname);
721 string const classpath = onlyPath(classname);
722 string const path = isabsolute ? classpath
723 : FileName(addPath(filepath.absFileName(),
724 classpath)).realPath();
725 string const oldpath = isabsolute ? string()
726 : FileName(addPath(origin, classpath)).realPath();
727 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
729 // that returns non-empty if a "local" layout file is found.
731 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
732 from_utf8(filepath.absFileName())));
735 setBaseClass(onlyFileName(tcp));
737 setBaseClass(onlyFileName(classname));
738 // We assume that a tex class exists for local or unknown
739 // layouts so this warning, will only be given for system layouts.
740 if (!baseClass()->isTeXClassAvailable()) {
741 docstring const desc =
742 translateIfPossible(from_utf8(baseClass()->description()));
743 docstring const prereqs =
744 from_utf8(baseClass()->prerequisites());
745 docstring const msg =
746 bformat(_("The selected document class\n"
748 "requires external files that are not available.\n"
749 "The document class can still be used, but the\n"
750 "document cannot be compiled until the following\n"
751 "prerequisites are installed:\n"
753 "See section 3.1.2.2 (Class Availability) of the\n"
754 "User's Guide for more information."), desc, prereqs);
755 frontend::Alert::warning(_("Document class not available"),
758 } else if (token == "\\save_transient_properties") {
759 lex >> save_transient_properties;
760 } else if (token == "\\origin") {
762 origin = lex.getString();
763 string const sysdirprefix = "/systemlyxdir/";
764 if (prefixIs(origin, sysdirprefix)) {
766 if (inSystemDir(filepath, docsys))
767 origin.replace(0, sysdirprefix.length() - 1, docsys);
769 origin.replace(0, sysdirprefix.length() - 1,
770 package().system_support().absFileName());
772 } else if (token == "\\begin_preamble") {
774 } else if (token == "\\begin_local_layout") {
775 readLocalLayout(lex, false);
776 } else if (token == "\\begin_forced_local_layout") {
777 readLocalLayout(lex, true);
778 } else if (token == "\\begin_modules") {
780 } else if (token == "\\begin_removed_modules") {
781 readRemovedModules(lex);
782 } else if (token == "\\begin_includeonly") {
783 readIncludeonly(lex);
784 } else if (token == "\\maintain_unincluded_children") {
788 maintain_unincluded_children = CM_None;
789 else if (tmp == "mostly")
790 maintain_unincluded_children = CM_Mostly;
791 else if (tmp == "strict")
792 maintain_unincluded_children = CM_Strict;
793 } else if (token == "\\options") {
795 options = lex.getString();
796 } else if (token == "\\use_default_options") {
797 lex >> use_default_options;
798 } else if (token == "\\master") {
800 master = lex.getString();
801 if (!filepath.empty() && FileName::isAbsolute(origin)) {
802 bool const isabs = FileName::isAbsolute(master);
803 FileName const abspath(isabs ? master : origin + master);
804 bool const moved = filepath != FileName(origin);
805 if (moved && abspath.exists()) {
806 docstring const path = isabs
808 : from_utf8(abspath.realPath());
809 docstring const refpath =
810 from_utf8(filepath.absFileName());
811 master = to_utf8(makeRelPath(path, refpath));
814 } else if (token == "\\suppress_date") {
815 lex >> suppress_date;
816 } else if (token == "\\justification") {
817 lex >> justification;
818 } else if (token == "\\language") {
820 } else if (token == "\\language_package") {
822 lang_package = lex.getString();
823 } else if (token == "\\inputencoding") {
825 } else if (token == "\\graphics") {
826 readGraphicsDriver(lex);
827 } else if (token == "\\default_output_format") {
828 lex >> default_output_format;
829 } else if (token == "\\bibtex_command") {
831 bibtex_command = lex.getString();
832 } else if (token == "\\index_command") {
834 index_command = lex.getString();
835 } else if (token == "\\fontencoding") {
837 fontenc = lex.getString();
838 } else if (token == "\\font_roman") {
839 lex >> fonts_roman[0];
840 lex >> fonts_roman[1];
841 } else if (token == "\\font_sans") {
842 lex >> fonts_sans[0];
843 lex >> fonts_sans[1];
844 } else if (token == "\\font_typewriter") {
845 lex >> fonts_typewriter[0];
846 lex >> fonts_typewriter[1];
847 } else if (token == "\\font_math") {
848 lex >> fonts_math[0];
849 lex >> fonts_math[1];
850 } else if (token == "\\font_default_family") {
851 lex >> fonts_default_family;
852 } else if (token == "\\use_non_tex_fonts") {
853 lex >> useNonTeXFonts;
854 } else if (token == "\\font_sc") {
855 lex >> fonts_expert_sc;
856 } else if (token == "\\font_roman_osf") {
857 lex >> fonts_roman_osf;
858 } else if (token == "\\font_sans_osf") {
859 lex >> fonts_sans_osf;
860 } else if (token == "\\font_typewriter_osf") {
861 lex >> fonts_typewriter_osf;
862 } else if (token == "\\font_roman_opts") {
863 lex >> font_roman_opts;
864 } else if (token == "\\font_sf_scale") {
865 lex >> fonts_sans_scale[0];
866 lex >> fonts_sans_scale[1];
867 } else if (token == "\\font_sans_opts") {
868 lex >> font_sans_opts;
869 } else if (token == "\\font_tt_scale") {
870 lex >> fonts_typewriter_scale[0];
871 lex >> fonts_typewriter_scale[1];
872 } else if (token == "\\font_typewriter_opts") {
873 lex >> font_typewriter_opts;
874 } else if (token == "\\font_cjk") {
876 } else if (token == "\\use_microtype") {
877 lex >> use_microtype;
878 } else if (token == "\\use_dash_ligatures") {
879 lex >> use_dash_ligatures;
880 } else if (token == "\\paragraph_separation") {
883 paragraph_separation = parseptranslator().find(parsep);
884 } else if (token == "\\paragraph_indentation") {
886 string parindent = lex.getString();
887 if (parindent == "default")
888 pimpl_->parindent = Length();
890 pimpl_->parindent = Length(parindent);
891 } else if (token == "\\defskip") {
893 string const defskip = lex.getString();
894 pimpl_->defskip = VSpace(defskip);
895 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
897 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
898 } else if (token == "\\is_math_indent") {
899 lex >> is_math_indent;
900 } else if (token == "\\math_indentation") {
902 string mathindent = lex.getString();
903 if (mathindent == "default")
904 pimpl_->mathindent = Length();
906 pimpl_->mathindent = Length(mathindent);
907 } else if (token == "\\math_numbering_side") {
911 math_numbering_side = LEFT;
912 else if (tmp == "right")
913 math_numbering_side = RIGHT;
915 math_numbering_side = DEFAULT;
916 } else if (token == "\\quotes_style") {
919 quotes_style = quotesstyletranslator().find(qstyle);
920 } else if (token == "\\dynamic_quotes") {
921 lex >> dynamic_quotes;
922 } else if (token == "\\papersize") {
925 papersize = papersizetranslator().find(ppsize);
926 } else if (token == "\\use_geometry") {
928 } else if (token == "\\use_package") {
933 use_package(package, packagetranslator().find(use));
934 } else if (token == "\\cite_engine") {
936 cite_engine_ = lex.getString();
937 } else if (token == "\\cite_engine_type") {
940 cite_engine_type_ = theCiteEnginesList.getType(engine_type);
941 } else if (token == "\\biblio_style") {
943 biblio_style = lex.getString();
944 } else if (token == "\\biblio_options") {
946 biblio_opts = trim(lex.getString());
947 } else if (token == "\\biblatex_bibstyle") {
949 biblatex_bibstyle = trim(lex.getString());
950 } else if (token == "\\biblatex_citestyle") {
952 biblatex_citestyle = trim(lex.getString());
953 } else if (token == "\\use_bibtopic") {
955 } else if (token == "\\multibib") {
957 } else if (token == "\\use_indices") {
959 } else if (token == "\\tracking_changes") {
960 lex >> track_changes;
961 } else if (token == "\\output_changes") {
962 lex >> output_changes;
963 } else if (token == "\\change_bars") {
965 } else if (token == "\\postpone_fragile_content") {
966 lex >> postpone_fragile_content;
967 } else if (token == "\\branch") {
969 docstring branch = lex.getDocString();
970 branchlist().add(branch);
973 string const tok = lex.getString();
974 if (tok == "\\end_branch")
976 Branch * branch_ptr = branchlist().find(branch);
977 if (tok == "\\selected") {
980 branch_ptr->setSelected(lex.getInteger());
982 if (tok == "\\filename_suffix") {
985 branch_ptr->setFileNameSuffix(lex.getInteger());
987 if (tok == "\\color") {
989 string color = lex.getString();
991 branch_ptr->setColor(color);
992 // Update also the Color table:
994 color = lcolor.getX11Name(Color_background);
996 lcolor.setColor(to_utf8(branch), color);
999 } else if (token == "\\index") {
1001 docstring index = lex.getDocString();
1003 indiceslist().add(index);
1006 string const tok = lex.getString();
1007 if (tok == "\\end_index")
1009 Index * index_ptr = indiceslist().find(index);
1010 if (tok == "\\shortcut") {
1012 shortcut = lex.getDocString();
1014 index_ptr->setShortcut(shortcut);
1016 if (tok == "\\color") {
1018 string color = lex.getString();
1020 index_ptr->setColor(color);
1021 // Update also the Color table:
1022 if (color == "none")
1023 color = lcolor.getX11Name(Color_background);
1025 if (!shortcut.empty())
1026 lcolor.setColor(to_utf8(shortcut), color);
1029 } else if (token == "\\author") {
1031 istringstream ss(lex.getString());
1035 } else if (token == "\\paperorientation") {
1038 orientation = paperorientationtranslator().find(orient);
1039 } else if (token == "\\backgroundcolor") {
1041 backgroundcolor = lyx::rgbFromHexName(lex.getString());
1042 isbackgroundcolor = true;
1043 } else if (token == "\\fontcolor") {
1045 fontcolor = lyx::rgbFromHexName(lex.getString());
1047 } else if (token == "\\notefontcolor") {
1049 string color = lex.getString();
1050 notefontcolor = lyx::rgbFromHexName(color);
1051 lcolor.setColor("notefontcolor", color);
1052 } else if (token == "\\boxbgcolor") {
1054 string color = lex.getString();
1055 boxbgcolor = lyx::rgbFromHexName(color);
1056 lcolor.setColor("boxbgcolor", color);
1057 } else if (token == "\\paperwidth") {
1059 } else if (token == "\\paperheight") {
1061 } else if (token == "\\leftmargin") {
1063 } else if (token == "\\topmargin") {
1065 } else if (token == "\\rightmargin") {
1067 } else if (token == "\\bottommargin") {
1068 lex >> bottommargin;
1069 } else if (token == "\\headheight") {
1071 } else if (token == "\\headsep") {
1073 } else if (token == "\\footskip") {
1075 } else if (token == "\\columnsep") {
1077 } else if (token == "\\paperfontsize") {
1079 } else if (token == "\\papercolumns") {
1081 } else if (token == "\\listings_params") {
1084 listings_params = InsetListingsParams(par).params();
1085 } else if (token == "\\papersides") {
1088 sides = sidestranslator().find(psides);
1089 } else if (token == "\\paperpagestyle") {
1091 } else if (token == "\\tablestyle") {
1093 } else if (token == "\\bullet") {
1095 } else if (token == "\\bulletLaTeX") {
1096 readBulletsLaTeX(lex);
1097 } else if (token == "\\secnumdepth") {
1099 } else if (token == "\\tocdepth") {
1101 } else if (token == "\\spacing") {
1105 if (nspacing == "other") {
1108 spacing().set(spacetranslator().find(nspacing), tmp_val);
1109 } else if (token == "\\float_placement") {
1110 lex >> float_placement;
1111 } else if (token == "\\float_alignment") {
1112 lex >> float_alignment;
1114 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
1115 string toktmp = pdfoptions().readToken(lex, token);
1116 if (!toktmp.empty()) {
1117 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
1121 } else if (token == "\\html_math_output") {
1124 html_math_output = static_cast<MathOutput>(temp);
1125 } else if (token == "\\html_be_strict") {
1126 lex >> html_be_strict;
1127 } else if (token == "\\html_css_as_file") {
1128 lex >> html_css_as_file;
1129 } else if (token == "\\html_math_img_scale") {
1130 lex >> html_math_img_scale;
1131 } else if (token == "\\html_latex_start") {
1133 html_latex_start = lex.getString();
1134 } else if (token == "\\html_latex_end") {
1136 html_latex_end = lex.getString();
1137 } else if (token == "\\output_sync") {
1139 } else if (token == "\\output_sync_macro") {
1140 lex >> output_sync_macro;
1141 } else if (token == "\\use_refstyle") {
1142 lex >> use_refstyle;
1143 } else if (token == "\\use_minted") {
1145 } else if (token == "\\use_lineno") {
1147 } else if (token == "\\lineno_options") {
1149 lineno_opts = trim(lex.getString());
1151 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1161 // Quote argument if it contains spaces
1162 string quoteIfNeeded(string const & str) {
1163 if (contains(str, ' '))
1164 return "\"" + str + "\"";
1170 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1172 // The top of the file is written by the buffer.
1173 // Prints out the buffer info into the .lyx file given by file
1175 os << "\\save_transient_properties "
1176 << convert<string>(save_transient_properties) << '\n';
1178 // the document directory (must end with a path separator)
1179 // realPath() is used to resolve symlinks, while addPath(..., "")
1180 // ensures a trailing path separator.
1182 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1183 string const sysdir = inSystemDir(FileName(filepath), docsys) ? docsys
1184 : addPath(package().system_support().realPath(), "");
1185 string const relpath =
1186 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1187 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1188 filepath = addPath("/systemlyxdir", relpath);
1189 else if (!save_transient_properties || !lyxrc.save_origin)
1190 filepath = "unavailable";
1191 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1194 os << "\\textclass "
1195 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1196 baseClass()->name()), "layout"))
1199 // then the preamble
1200 if (!preamble.empty()) {
1201 // remove '\n' from the end of preamble
1202 docstring const tmppreamble = rtrim(preamble, "\n");
1203 os << "\\begin_preamble\n"
1204 << to_utf8(tmppreamble)
1205 << "\n\\end_preamble\n";
1209 if (!options.empty()) {
1210 os << "\\options " << options << '\n';
1213 // use the class options defined in the layout?
1214 os << "\\use_default_options "
1215 << convert<string>(use_default_options) << "\n";
1217 // the master document
1218 if (!master.empty()) {
1219 os << "\\master " << master << '\n';
1223 if (!removed_modules_.empty()) {
1224 os << "\\begin_removed_modules" << '\n';
1225 for (auto const & mod : removed_modules_)
1227 os << "\\end_removed_modules" << '\n';
1231 if (!layout_modules_.empty()) {
1232 os << "\\begin_modules" << '\n';
1233 for (auto const & mod : layout_modules_)
1235 os << "\\end_modules" << '\n';
1239 if (!included_children_.empty()) {
1240 os << "\\begin_includeonly" << '\n';
1241 for (auto const & c : included_children_)
1243 os << "\\end_includeonly" << '\n';
1246 switch (maintain_unincluded_children) {
1257 os << "\\maintain_unincluded_children " << muc << '\n';
1259 // local layout information
1260 docstring const local_layout = getLocalLayout(false);
1261 if (!local_layout.empty()) {
1262 // remove '\n' from the end
1263 docstring const tmplocal = rtrim(local_layout, "\n");
1264 os << "\\begin_local_layout\n"
1265 << to_utf8(tmplocal)
1266 << "\n\\end_local_layout\n";
1268 docstring const forced_local_layout = getLocalLayout(true);
1269 if (!forced_local_layout.empty()) {
1270 // remove '\n' from the end
1271 docstring const tmplocal = rtrim(forced_local_layout, "\n");
1272 os << "\\begin_forced_local_layout\n"
1273 << to_utf8(tmplocal)
1274 << "\n\\end_forced_local_layout\n";
1277 // then the text parameters
1278 if (language != ignore_language)
1279 os << "\\language " << language->lang() << '\n';
1280 os << "\\language_package " << lang_package
1281 << "\n\\inputencoding " << inputenc
1282 << "\n\\fontencoding " << fontenc
1283 << "\n\\font_roman \"" << fonts_roman[0]
1284 << "\" \"" << fonts_roman[1] << '"'
1285 << "\n\\font_sans \"" << fonts_sans[0]
1286 << "\" \"" << fonts_sans[1] << '"'
1287 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1288 << "\" \"" << fonts_typewriter[1] << '"'
1289 << "\n\\font_math \"" << fonts_math[0]
1290 << "\" \"" << fonts_math[1] << '"'
1291 << "\n\\font_default_family " << fonts_default_family
1292 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1293 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1294 << "\n\\font_roman_osf " << convert<string>(fonts_roman_osf)
1295 << "\n\\font_sans_osf " << convert<string>(fonts_sans_osf)
1296 << "\n\\font_typewriter_osf " << convert<string>(fonts_typewriter_osf);
1297 if (!font_roman_opts.empty())
1298 os << "\n\\font_roman_opts \"" << font_roman_opts << "\"";
1299 os << "\n\\font_sf_scale " << fonts_sans_scale[0]
1300 << ' ' << fonts_sans_scale[1];
1301 if (!font_sans_opts.empty())
1302 os << "\n\\font_sans_opts \"" << font_sans_opts << "\"";
1303 os << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1304 << ' ' << fonts_typewriter_scale[1];
1305 if (!font_typewriter_opts.empty())
1306 os << "\n\\font_typewriter_opts \"" << font_typewriter_opts << "\"";
1308 if (!fonts_cjk.empty())
1309 os << "\\font_cjk " << fonts_cjk << '\n';
1310 os << "\\use_microtype " << convert<string>(use_microtype) << '\n';
1311 os << "\\use_dash_ligatures " << convert<string>(use_dash_ligatures) << '\n';
1312 os << "\\graphics " << graphics_driver << '\n';
1313 os << "\\default_output_format " << default_output_format << '\n';
1314 os << "\\output_sync " << output_sync << '\n';
1315 if (!output_sync_macro.empty())
1316 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1317 os << "\\bibtex_command " << bibtex_command << '\n';
1318 os << "\\index_command " << index_command << '\n';
1320 if (!float_placement.empty())
1321 os << "\\float_placement " << float_placement << '\n';
1322 if (!float_alignment.empty())
1323 os << "\\float_alignment " << float_alignment << '\n';
1324 os << "\\paperfontsize " << fontsize << '\n';
1326 spacing().writeFile(os);
1327 pdfoptions().writeFile(os);
1329 os << "\\papersize " << string_papersize[papersize]
1330 << "\n\\use_geometry " << convert<string>(use_geometry);
1331 map<string, string> const & packages = auto_packages();
1332 for (auto const & pack : packages)
1333 os << "\n\\use_package " << pack.first << ' '
1334 << use_package(pack.first);
1336 os << "\n\\cite_engine ";
1338 if (!cite_engine_.empty())
1343 os << "\n\\cite_engine_type " << theCiteEnginesList.getTypeAsString(cite_engine_type_);
1345 if (!biblio_style.empty())
1346 os << "\n\\biblio_style " << biblio_style;
1347 if (!biblio_opts.empty())
1348 os << "\n\\biblio_options " << biblio_opts;
1349 if (!biblatex_bibstyle.empty())
1350 os << "\n\\biblatex_bibstyle " << biblatex_bibstyle;
1351 if (!biblatex_citestyle.empty())
1352 os << "\n\\biblatex_citestyle " << biblatex_citestyle;
1353 if (!multibib.empty())
1354 os << "\n\\multibib " << multibib;
1356 os << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1357 << "\n\\use_indices " << convert<string>(use_indices)
1358 << "\n\\paperorientation " << string_orientation[orientation]
1359 << "\n\\suppress_date " << convert<string>(suppress_date)
1360 << "\n\\justification " << convert<string>(justification)
1361 << "\n\\use_refstyle " << use_refstyle
1362 << "\n\\use_minted " << use_minted
1363 << "\n\\use_lineno " << use_lineno
1366 if (!lineno_opts.empty())
1367 os << "\\lineno_options " << lineno_opts << '\n';
1369 if (isbackgroundcolor == true)
1370 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1371 if (isfontcolor == true)
1372 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1373 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1374 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1375 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1376 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1378 for (auto const & br : branchlist()) {
1379 os << "\\branch " << to_utf8(br.branch())
1380 << "\n\\selected " << br.isSelected()
1381 << "\n\\filename_suffix " << br.hasFileNameSuffix()
1382 << "\n\\color " << lyx::X11hexname(br.color())
1387 for (auto const & id : indiceslist()) {
1388 os << "\\index " << to_utf8(id.index())
1389 << "\n\\shortcut " << to_utf8(id.shortcut())
1390 << "\n\\color " << lyx::X11hexname(id.color())
1395 if (!paperwidth.empty())
1396 os << "\\paperwidth "
1397 << VSpace(paperwidth).asLyXCommand() << '\n';
1398 if (!paperheight.empty())
1399 os << "\\paperheight "
1400 << VSpace(paperheight).asLyXCommand() << '\n';
1401 if (!leftmargin.empty())
1402 os << "\\leftmargin "
1403 << VSpace(leftmargin).asLyXCommand() << '\n';
1404 if (!topmargin.empty())
1405 os << "\\topmargin "
1406 << VSpace(topmargin).asLyXCommand() << '\n';
1407 if (!rightmargin.empty())
1408 os << "\\rightmargin "
1409 << VSpace(rightmargin).asLyXCommand() << '\n';
1410 if (!bottommargin.empty())
1411 os << "\\bottommargin "
1412 << VSpace(bottommargin).asLyXCommand() << '\n';
1413 if (!headheight.empty())
1414 os << "\\headheight "
1415 << VSpace(headheight).asLyXCommand() << '\n';
1416 if (!headsep.empty())
1418 << VSpace(headsep).asLyXCommand() << '\n';
1419 if (!footskip.empty())
1421 << VSpace(footskip).asLyXCommand() << '\n';
1422 if (!columnsep.empty())
1423 os << "\\columnsep "
1424 << VSpace(columnsep).asLyXCommand() << '\n';
1425 os << "\\secnumdepth " << secnumdepth
1426 << "\n\\tocdepth " << tocdepth
1427 << "\n\\paragraph_separation "
1428 << string_paragraph_separation[paragraph_separation];
1429 if (!paragraph_separation)
1430 os << "\n\\paragraph_indentation "
1431 << (getParIndent().empty() ? "default" : getParIndent().asString());
1433 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1434 os << "\n\\is_math_indent " << is_math_indent;
1436 os << "\n\\math_indentation "
1437 << (getMathIndent().empty() ? "default" : getMathIndent().asString());
1438 os << "\n\\math_numbering_side ";
1439 switch(math_numbering_side) {
1449 os << "\n\\quotes_style "
1450 << string_quotes_style[quotes_style]
1451 << "\n\\dynamic_quotes " << dynamic_quotes
1452 << "\n\\papercolumns " << columns
1453 << "\n\\papersides " << sides
1454 << "\n\\paperpagestyle " << pagestyle
1455 << "\n\\tablestyle " << tablestyle << '\n';
1456 if (!listings_params.empty())
1457 os << "\\listings_params \"" <<
1458 InsetListingsParams(listings_params).encodedString() << "\"\n";
1459 for (int i = 0; i < 4; ++i) {
1460 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1461 if (user_defined_bullet(i).getFont() != -1) {
1462 os << "\\bullet " << i << " "
1463 << user_defined_bullet(i).getFont() << " "
1464 << user_defined_bullet(i).getCharacter() << " "
1465 << user_defined_bullet(i).getSize() << "\n";
1469 os << "\\bulletLaTeX " << i << " \""
1470 << lyx::to_ascii(user_defined_bullet(i).getText())
1476 os << "\\tracking_changes "
1477 << (save_transient_properties ? convert<string>(track_changes) : "false")
1480 os << "\\output_changes "
1481 << (save_transient_properties ? convert<string>(output_changes) : "false")
1484 os << "\\change_bars "
1485 << (save_transient_properties ? convert<string>(change_bars) : "false")
1488 os << "\\postpone_fragile_content " << convert<string>(postpone_fragile_content) << '\n';
1490 os << "\\html_math_output " << html_math_output << '\n'
1491 << "\\html_css_as_file " << html_css_as_file << '\n'
1492 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1494 if (html_math_img_scale != 1.0)
1495 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1496 if (!html_latex_start.empty())
1497 os << "\\html_latex_start " << html_latex_start << '\n';
1498 if (!html_latex_end.empty())
1499 os << "\\html_latex_end " << html_latex_end << '\n';
1501 os << pimpl_->authorlist;
1505 void BufferParams::validate(LaTeXFeatures & features) const
1507 features.require(documentClass().required());
1509 if (columns > 1 && language->rightToLeft())
1510 features.require("rtloutputdblcol");
1512 if (output_changes) {
1513 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1514 LaTeXFeatures::isAvailable("xcolor");
1516 switch (features.runparams().flavor) {
1517 case OutputParams::LATEX:
1518 case OutputParams::DVILUATEX:
1520 features.require("ct-xcolor-ulem");
1521 features.require("ulem");
1522 features.require("xcolor");
1524 features.require("ct-none");
1527 case OutputParams::LUATEX:
1528 case OutputParams::PDFLATEX:
1529 case OutputParams::XETEX:
1531 features.require("ct-xcolor-ulem");
1532 features.require("ulem");
1533 features.require("xcolor");
1534 // improves color handling in PDF output
1535 features.require("pdfcolmk");
1537 features.require("ct-none");
1544 features.require("changebar");
1547 // Floats with 'Here definitely' as default setting.
1548 if (float_placement.find('H') != string::npos)
1549 features.require("float");
1551 for (auto const & pm : use_packages) {
1552 if (pm.first == "amsmath") {
1553 // AMS Style is at document level
1554 if (pm.second == package_on ||
1555 features.isProvided("amsmath"))
1556 features.require(pm.first);
1557 } else if (pm.second == package_on)
1558 features.require(pm.first);
1561 // Document-level line spacing
1562 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1563 features.require("setspace");
1565 // the bullet shapes are buffer level not paragraph level
1566 // so they are tested here
1567 for (int i = 0; i < 4; ++i) {
1568 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1570 int const font = user_defined_bullet(i).getFont();
1572 int const c = user_defined_bullet(i).getCharacter();
1578 features.require("latexsym");
1580 } else if (font == 1) {
1581 features.require("amssymb");
1582 } else if (font >= 2 && font <= 5) {
1583 features.require("pifont");
1587 if (pdfoptions().use_hyperref) {
1588 features.require("hyperref");
1589 // due to interferences with babel and hyperref, the color package has to
1590 // be loaded after hyperref when hyperref is used with the colorlinks
1591 // option, see http://www.lyx.org/trac/ticket/5291
1592 if (pdfoptions().colorlinks)
1593 features.require("color");
1595 if (!listings_params.empty()) {
1596 // do not test validity because listings_params is
1597 // supposed to be valid
1599 InsetListingsParams(listings_params).separatedParams(true);
1600 // we can't support all packages, but we should load the color package
1601 if (par.find("\\color", 0) != string::npos)
1602 features.require("color");
1605 // some languages are only available via polyglossia
1606 if (features.hasPolyglossiaExclusiveLanguages())
1607 features.require("polyglossia");
1609 if (useNonTeXFonts && fontsMath() != "auto")
1610 features.require("unicode-math");
1613 features.require("microtype");
1615 if (!language->required().empty())
1616 features.require(language->required());
1620 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1621 FileName const & filepath) const
1623 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1624 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1625 // \RequirePackage to do so, rather than the normal \usepackage
1626 // Do not try to load any other package before the document class, unless you
1627 // have a thorough understanding of the LATEX internals and know exactly what you
1629 if (features.mustProvide("fix-cm"))
1630 os << "\\RequirePackage{fix-cm}\n";
1631 // Likewise for fixltx2e. If other packages conflict with this policy,
1632 // treat it as a package bug (and report it!)
1633 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1634 if (features.mustProvide("fixltx2e"))
1635 os << "\\RequirePackage{fixltx2e}\n";
1637 os << "\\documentclass";
1639 DocumentClass const & tclass = documentClass();
1641 ostringstream clsoptions; // the document class options.
1643 if (tokenPos(tclass.opt_fontsize(),
1644 '|', fontsize) >= 0) {
1645 // only write if existing in list (and not default)
1646 clsoptions << subst(tclass.fontsizeformat(), "$$s", fontsize) << ",";
1649 // paper sizes not supported by the class itself need the
1651 vector<string> classpsizes = getVectorFromString(tclass.opt_pagesize(), "|");
1652 bool class_supported_papersize = papersize == PAPER_DEFAULT
1653 || find(classpsizes.begin(), classpsizes.end(), string_papersize[papersize]) != classpsizes.end();
1655 if ((!use_geometry || features.isProvided("geometry-light"))
1656 && class_supported_papersize && papersize != PAPER_DEFAULT)
1657 clsoptions << subst(tclass.pagesizeformat(), "$$s", string_papersize[papersize]) << ",";
1660 if (sides != tclass.sides()) {
1663 clsoptions << "oneside,";
1666 clsoptions << "twoside,";
1672 if (columns != tclass.columns()) {
1674 clsoptions << "twocolumn,";
1676 clsoptions << "onecolumn,";
1680 && orientation == ORIENTATION_LANDSCAPE)
1681 clsoptions << "landscape,";
1684 clsoptions << "fleqn,";
1686 switch(math_numbering_side) {
1688 clsoptions << "leqno,";
1691 clsoptions << "reqno,";
1692 features.require("amsmath");
1698 // language should be a parameter to \documentclass
1699 if (language->babel() == "hebrew"
1700 && default_language->babel() != "hebrew")
1701 // This seems necessary
1702 features.useLanguage(default_language);
1704 ostringstream language_options;
1705 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1706 bool const use_polyglossia = features.usePolyglossia();
1707 bool const global = lyxrc.language_global_options;
1708 if (features.useBabel() || (use_polyglossia && global)) {
1709 language_options << features.getBabelLanguages();
1710 if (!language->babel().empty()) {
1711 if (!language_options.str().empty())
1712 language_options << ',';
1713 language_options << language->babel();
1715 if (global && !language_options.str().empty())
1716 clsoptions << language_options.str() << ',';
1719 // the predefined options from the layout
1720 if (use_default_options && !tclass.options().empty())
1721 clsoptions << tclass.options() << ',';
1723 // the user-defined options
1724 if (!options.empty()) {
1725 clsoptions << options << ',';
1728 docstring const strOptions = from_utf8(clsoptions.str());
1729 if (!strOptions.empty()) {
1730 // Check if class options contain uncodable glyphs
1731 docstring uncodable_glyphs;
1732 docstring options_encodable;
1733 Encoding const * const enc = features.runparams().encoding;
1735 for (size_t n = 0; n < strOptions.size(); ++n) {
1736 char_type c = strOptions[n];
1737 if (!enc->encodable(c)) {
1738 docstring const glyph(1, c);
1739 LYXERR0("Uncodable character '"
1741 << "' in class options!");
1742 uncodable_glyphs += glyph;
1743 if (features.runparams().dryrun) {
1744 options_encodable += "<" + _("LyX Warning: ")
1745 + _("uncodable character") + " '";
1746 options_encodable += c;
1747 options_encodable += "'>";
1750 options_encodable += c;
1753 options_encodable = strOptions;
1755 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
1756 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
1757 frontend::Alert::warning(
1758 _("Uncodable character in class options"),
1760 _("The class options of your document contain glyphs "
1761 "that are unknown in the current document encoding "
1762 "(namely %1$s).\nThese glyphs are omitted "
1763 " from the output, which may result in "
1764 "incomplete output."
1765 "\n\nPlease select an appropriate "
1766 "document encoding\n"
1767 "(such as utf8) or change the "
1768 "class options accordingly."),
1771 options_encodable = rtrim(options_encodable, ",");
1772 os << '[' << options_encodable << ']';
1775 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1776 // end of \documentclass defs
1778 // The package options (via \PassOptionsToPackage)
1779 os << from_ascii(features.getPackageOptions());
1781 // if we use fontspec or newtxmath, we have to load the AMS packages here
1782 string const ams = features.loadAMSPackages();
1783 bool const ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1");
1784 bool const use_newtxmath =
1785 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1786 ot1, false, false) == "newtxmath";
1787 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1788 os << from_ascii(ams);
1790 if (useNonTeXFonts) {
1791 // Babel (as of 2017/11/03) loads fontspec itself
1792 if (!features.isProvided("fontspec")
1793 && !(features.useBabel() && features.isAvailable("babel-2017/11/03")))
1794 os << "\\usepackage{fontspec}\n";
1795 if (features.mustProvide("unicode-math")
1796 && features.isAvailable("unicode-math"))
1797 os << "\\usepackage{unicode-math}\n";
1800 // load CJK support package before font selection
1801 // (see autotests/export/latex/CJK/micro-sign_utf8-cjk-libertine.lyx)
1802 if (!useNonTeXFonts && encoding().package() != Encoding::none && inputenc != "utf8x"
1803 && (encoding().package() == Encoding::CJK || features.mustProvide("CJK"))) {
1804 if (inputenc == "utf8-cjk" || inputenc == "utf8")
1805 os << "\\usepackage{CJKutf8}\n";
1807 os << "\\usepackage[encapsulated]{CJK}\n";
1810 // font selection must be done before loading fontenc.sty
1811 // but after babel with non-TeX fonts
1812 string const fonts = loadFonts(features);
1813 if (!fonts.empty() && (!features.useBabel() || !useNonTeXFonts))
1814 os << from_utf8(fonts);
1816 if (fonts_default_family != "default")
1817 os << "\\renewcommand{\\familydefault}{\\"
1818 << from_ascii(fonts_default_family) << "}\n";
1820 // set font encoding
1821 // non-TeX fonts use font encoding TU (set by fontspec)
1822 if (!useNonTeXFonts && !features.isProvided("fontenc")
1823 && main_font_encoding() != "default") {
1824 // get main font encodings
1825 vector<string> fontencs = font_encodings();
1826 // get font encodings of secondary languages
1827 // FIXME: some languages (hebrew, ...) assume a standard font encoding as last
1828 // option (for text in other languages).
1829 features.getFontEncodings(fontencs);
1830 if (!fontencs.empty()) {
1831 os << "\\usepackage["
1832 << from_ascii(getStringFromVector(fontencs))
1837 // Load textcomp and pmboxdraw before (lua)inputenc (#11454)
1838 if (features.mustProvide("textcomp"))
1839 os << "\\usepackage{textcomp}\n";
1840 if (features.mustProvide("pmboxdraw"))
1841 os << "\\usepackage{pmboxdraw}\n";
1843 // handle inputenc etc.
1844 // (In documents containing text in Thai language,
1845 // we must load inputenc after babel, see lib/languages).
1846 if (!contains(features.getBabelPostsettings(), from_ascii("thai.ldf")))
1847 writeEncodingPreamble(os, features);
1850 if (!features.runparams().includeall && !included_children_.empty()) {
1851 os << "\\includeonly{";
1853 for (auto incfile : included_children_) {
1854 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1855 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1857 if (!features.runparams().nice)
1859 // \includeonly doesn't want an extension
1860 incfile = changeExtension(incfile, string());
1861 incfile = support::latex_path(incfile);
1862 if (!incfile.empty()) {
1865 os << from_utf8(incfile);
1872 if (!features.isProvided("geometry")
1873 && (use_geometry || !class_supported_papersize)) {
1874 odocstringstream ods;
1875 if (!getGraphicsDriver("geometry").empty())
1876 ods << getGraphicsDriver("geometry");
1877 if (orientation == ORIENTATION_LANDSCAPE)
1878 ods << ",landscape";
1879 switch (papersize) {
1881 if (!paperwidth.empty())
1882 ods << ",paperwidth="
1883 << from_ascii(paperwidth);
1884 if (!paperheight.empty())
1885 ods << ",paperheight="
1886 << from_ascii(paperheight);
1888 case PAPER_USLETTER:
1890 case PAPER_USEXECUTIVE:
1919 ods << "," << from_ascii(string_papersize_geometry[papersize]);
1924 docstring g_options = trim(ods.str(), ",");
1925 os << "\\usepackage";
1926 // geometry-light means that the class works with geometry, but overwrites
1927 // the package options and paper sizes (memoir does this).
1928 // In this case, all options need to go to \geometry
1929 // and the standard paper sizes need to go to the class options.
1930 if (!g_options.empty() && !features.isProvided("geometry-light")) {
1931 os << '[' << g_options << ']';
1934 os << "{geometry}\n";
1935 if (use_geometry || features.isProvided("geometry-light")) {
1936 os << "\\geometry{verbose";
1937 if (!g_options.empty())
1938 // Output general options here with "geometry light".
1939 os << "," << g_options;
1940 // output this only if use_geometry is true
1942 if (!topmargin.empty())
1943 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1944 if (!bottommargin.empty())
1945 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1946 if (!leftmargin.empty())
1947 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1948 if (!rightmargin.empty())
1949 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1950 if (!headheight.empty())
1951 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1952 if (!headsep.empty())
1953 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1954 if (!footskip.empty())
1955 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1956 if (!columnsep.empty())
1957 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1961 } else if (orientation == ORIENTATION_LANDSCAPE
1962 || papersize != PAPER_DEFAULT) {
1963 features.require("papersize");
1966 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1967 if (pagestyle == "fancy")
1968 os << "\\usepackage{fancyhdr}\n";
1969 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1972 // only output when the background color is not default
1973 if (isbackgroundcolor == true) {
1974 // only require color here, the background color will be defined
1975 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1977 features.require("color");
1978 features.require("pagecolor");
1981 // only output when the font color is not default
1982 if (isfontcolor == true) {
1983 // only require color here, the font color will be defined
1984 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1986 features.require("color");
1987 features.require("fontcolor");
1990 // Only if class has a ToC hierarchy
1991 if (tclass.hasTocLevels()) {
1992 if (secnumdepth != tclass.secnumdepth()) {
1993 os << "\\setcounter{secnumdepth}{"
1997 if (tocdepth != tclass.tocdepth()) {
1998 os << "\\setcounter{tocdepth}{"
2004 if (paragraph_separation) {
2005 // when skip separation
2006 switch (getDefSkip().kind()) {
2007 case VSpace::SMALLSKIP:
2008 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
2010 case VSpace::MEDSKIP:
2011 os << "\\setlength{\\parskip}{\\medskipamount}\n";
2013 case VSpace::BIGSKIP:
2014 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
2016 case VSpace::LENGTH:
2017 os << "\\setlength{\\parskip}{"
2018 << from_utf8(getDefSkip().length().asLatexString())
2021 default: // should never happen // Then delete it.
2022 os << "\\setlength{\\parskip}{\\medskipamount}\n";
2025 os << "\\setlength{\\parindent}{0pt}\n";
2027 // when separation by indentation
2028 // only output something when a width is given
2029 if (!getParIndent().empty()) {
2030 os << "\\setlength{\\parindent}{"
2031 << from_utf8(getParIndent().asLatexString())
2036 if (is_math_indent) {
2037 // when formula indentation
2038 // only output something when it is not the default
2039 if (!getMathIndent().empty()) {
2040 os << "\\setlength{\\mathindent}{"
2041 << from_utf8(getMathIndent().asString())
2046 // Now insert the LyX specific LaTeX commands...
2047 features.resolveAlternatives();
2048 features.expandMultiples();
2051 if (!output_sync_macro.empty())
2052 os << from_utf8(output_sync_macro) +"\n";
2053 else if (features.runparams().flavor == OutputParams::LATEX)
2054 os << "\\usepackage[active]{srcltx}\n";
2055 else if (features.runparams().flavor == OutputParams::PDFLATEX)
2056 os << "\\synctex=-1\n";
2059 // due to interferences with babel and hyperref, the color package has to
2060 // be loaded (when it is not already loaded) before babel when hyperref
2061 // is used with the colorlinks option, see
2062 // http://www.lyx.org/trac/ticket/5291
2063 // we decided therefore to load color always before babel, see
2064 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
2065 os << from_ascii(features.getColorOptions());
2067 // If we use hyperref, jurabib, japanese or varioref,
2068 // we have to call babel before
2070 && (features.isRequired("jurabib")
2071 || features.isRequired("hyperref")
2072 || features.isRequired("varioref")
2073 || features.isRequired("japanese"))) {
2074 os << features.getBabelPresettings();
2076 os << from_utf8(babelCall(language_options.str(),
2077 !lyxrc.language_global_options)) + '\n';
2078 os << features.getBabelPostsettings();
2081 // The optional packages;
2082 os << from_ascii(features.getPackages());
2084 // Additional Indices
2085 if (features.isRequired("splitidx")) {
2086 for (auto const & idx : indiceslist()) {
2087 os << "\\newindex{";
2088 os << escape(idx.shortcut());
2094 os << from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
2097 // * Hyperref manual: "Make sure it comes last of your loaded
2098 // packages, to give it a fighting chance of not being over-written,
2099 // since its job is to redefine many LaTeX commands."
2100 // * Email from Heiko Oberdiek: "It is usually better to load babel
2101 // before hyperref. Then hyperref has a chance to detect babel.
2102 // * Has to be loaded before the "LyX specific LaTeX commands" to
2103 // avoid errors with algorithm floats.
2104 // use hyperref explicitly if it is required
2105 if (features.isRequired("hyperref")) {
2106 OutputParams tmp_params = features.runparams();
2107 pdfoptions().writeLaTeX(tmp_params, os,
2108 features.isProvided("hyperref"));
2109 // correctly break URLs with hyperref and dvi/ps output
2110 if (features.runparams().hyperref_driver == "dvips"
2111 && features.isAvailable("breakurl"))
2112 os << "\\usepackage{breakurl}\n";
2113 } else if (features.isRequired("nameref"))
2114 // hyperref loads this automatically
2115 os << "\\usepackage{nameref}\n";
2118 os << "\\usepackage";
2119 if (!lineno_opts.empty())
2120 os << "[" << lineno_opts << "]";
2122 os << "\\linenumbers\n";
2125 // bibtopic needs to be loaded after hyperref.
2126 // the dot provides the aux file naming which LyX can detect.
2127 if (features.mustProvide("bibtopic"))
2128 os << "\\usepackage[dot]{bibtopic}\n";
2130 // Will be surrounded by \makeatletter and \makeatother when not empty
2131 otexstringstream atlyxpreamble;
2133 // Some macros LyX will need
2135 TexString tmppreamble = features.getMacros();
2136 if (!tmppreamble.str.empty())
2137 atlyxpreamble << "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2138 "LyX specific LaTeX commands.\n"
2139 << move(tmppreamble)
2142 // the text class specific preamble
2144 docstring tmppreamble = features.getTClassPreamble();
2145 if (!tmppreamble.empty())
2146 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2147 "Textclass specific LaTeX commands.\n"
2151 // suppress date if selected
2152 // use \@ifundefined because we cannot be sure that every document class
2153 // has a \date command
2155 atlyxpreamble << "\\@ifundefined{date}{}{\\date{}}\n";
2157 /* the user-defined preamble */
2158 if (!containsOnly(preamble, " \n\t")) {
2160 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2161 "User specified LaTeX commands.\n";
2163 // Check if the user preamble contains uncodable glyphs
2164 odocstringstream user_preamble;
2165 docstring uncodable_glyphs;
2166 Encoding const * const enc = features.runparams().encoding;
2168 for (size_t n = 0; n < preamble.size(); ++n) {
2169 char_type c = preamble[n];
2170 if (!enc->encodable(c)) {
2171 docstring const glyph(1, c);
2172 LYXERR0("Uncodable character '"
2174 << "' in user preamble!");
2175 uncodable_glyphs += glyph;
2176 if (features.runparams().dryrun) {
2177 user_preamble << "<" << _("LyX Warning: ")
2178 << _("uncodable character") << " '";
2179 user_preamble.put(c);
2180 user_preamble << "'>";
2183 user_preamble.put(c);
2186 user_preamble << preamble;
2188 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2189 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2190 frontend::Alert::warning(
2191 _("Uncodable character in user preamble"),
2193 _("The user preamble of your document contains glyphs "
2194 "that are unknown in the current document encoding "
2195 "(namely %1$s).\nThese glyphs are omitted "
2196 " from the output, which may result in "
2197 "incomplete output."
2198 "\n\nPlease select an appropriate "
2199 "document encoding\n"
2200 "(such as utf8) or change the "
2201 "preamble code accordingly."),
2204 atlyxpreamble << user_preamble.str() << '\n';
2207 // footmisc must be loaded after setspace
2208 // Load it here to avoid clashes with footmisc loaded in the user
2209 // preamble. For that reason we also pass the options via
2210 // \PassOptionsToPackage in getPreamble() and not here.
2211 if (features.mustProvide("footmisc"))
2212 atlyxpreamble << "\\usepackage{footmisc}\n";
2214 // subfig loads internally the LaTeX package "caption". As
2215 // caption is a very popular package, users will load it in
2216 // the preamble. Therefore we must load subfig behind the
2217 // user-defined preamble and check if the caption package was
2218 // loaded or not. For the case that caption is loaded before
2219 // subfig, there is the subfig option "caption=false". This
2220 // option also works when a koma-script class is used and
2221 // koma's own caption commands are used instead of caption. We
2222 // use \PassOptionsToPackage here because the user could have
2223 // already loaded subfig in the preamble.
2224 if (features.mustProvide("subfig"))
2225 atlyxpreamble << "\\@ifundefined{showcaptionsetup}{}{%\n"
2226 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2227 "\\usepackage{subfig}\n";
2229 // Itemize bullet settings need to be last in case the user
2230 // defines their own bullets that use a package included
2231 // in the user-defined preamble -- ARRae
2232 // Actually it has to be done much later than that
2233 // since some packages like frenchb make modifications
2234 // at \begin{document} time -- JMarc
2235 docstring bullets_def;
2236 for (int i = 0; i < 4; ++i) {
2237 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2238 if (bullets_def.empty())
2239 bullets_def += "\\AtBeginDocument{\n";
2240 bullets_def += " \\def\\labelitemi";
2242 // `i' is one less than the item to modify
2249 bullets_def += "ii";
2255 bullets_def += '{' +
2256 user_defined_bullet(i).getText()
2261 if (!bullets_def.empty())
2262 atlyxpreamble << bullets_def << "}\n\n";
2264 if (!atlyxpreamble.empty())
2265 os << "\n\\makeatletter\n"
2266 << atlyxpreamble.release()
2267 << "\\makeatother\n\n";
2269 // We try to load babel late, in case it interferes with other packages.
2270 // Jurabib, hyperref, varioref, bicaption, menukeys and listings (bug 8995)
2271 // have to be called after babel, though.
2272 if (use_babel && !features.isRequired("jurabib")
2273 && !features.isRequired("hyperref")
2274 && !features.isRequired("varioref")
2275 && !features.isRequired("japanese")) {
2276 os << features.getBabelPresettings();
2278 os << from_utf8(babelCall(language_options.str(),
2279 !lyxrc.language_global_options)) + '\n';
2280 os << features.getBabelPostsettings();
2282 // In documents containing text in Thai language,
2283 // we must load inputenc after babel (see lib/languages).
2284 if (contains(features.getBabelPostsettings(), from_ascii("thai.ldf")))
2285 writeEncodingPreamble(os, features);
2287 // font selection must be done after babel with non-TeX fonts
2288 if (!fonts.empty() && features.useBabel() && useNonTeXFonts)
2289 os << from_utf8(fonts);
2291 if (features.isRequired("bicaption"))
2292 os << "\\usepackage{bicaption}\n";
2293 if (!listings_params.empty()
2294 || features.mustProvide("listings")
2295 || features.mustProvide("minted")) {
2297 os << "\\usepackage{minted}\n";
2299 os << "\\usepackage{listings}\n";
2301 string lst_params = listings_params;
2302 // If minted, do not output the language option (bug 11203)
2303 if (use_minted && contains(lst_params, "language=")) {
2304 vector<string> opts =
2305 getVectorFromString(lst_params, ",", false);
2306 for (size_t i = 0; i < opts.size(); ++i) {
2307 if (prefixIs(opts[i], "language="))
2308 opts.erase(opts.begin() + i--);
2310 lst_params = getStringFromVector(opts, ",");
2312 if (!lst_params.empty()) {
2314 os << "\\setminted{";
2317 // do not test validity because listings_params is
2318 // supposed to be valid
2320 InsetListingsParams(lst_params).separatedParams(true);
2321 os << from_utf8(par);
2325 // xunicode only needs to be loaded if tipa is used
2326 // (the rest is obsoleted by the new TU encoding).
2327 // It needs to be loaded at least after amsmath, amssymb,
2328 // esint and the other packages that provide special glyphs
2329 if (features.mustProvide("tipa") && useNonTeXFonts
2330 && !features.isProvided("xunicode")) {
2331 // The `xunicode` package officially only supports XeTeX,
2332 // but also works with LuaTeX. We work around its XeTeX test.
2333 if (features.runparams().flavor != OutputParams::XETEX) {
2334 os << "% Pretend to xunicode that we are XeTeX\n"
2335 << "\\def\\XeTeXpicfile{}\n";
2337 os << "\\usepackage{xunicode}\n";
2340 // covington must be loaded after beamerarticle
2341 if (features.isRequired("covington"))
2342 os << "\\usepackage{covington}\n";
2344 // Polyglossia must be loaded last ...
2345 if (use_polyglossia) {
2347 os << "\\usepackage{polyglossia}\n";
2348 // set the main language
2349 os << "\\setdefaultlanguage";
2350 if (!language->polyglossiaOpts().empty())
2351 os << "[" << from_ascii(language->polyglossiaOpts()) << "]";
2352 os << "{" << from_ascii(language->polyglossia()) << "}\n";
2353 // now setup the other languages
2354 set<string> const polylangs =
2355 features.getPolyglossiaLanguages();
2356 for (auto const & pl : polylangs) {
2357 // We do not output the options here; they are output in
2358 // the language switch commands. This is safer if multiple
2359 // varieties are used.
2360 if (pl == language->polyglossia())
2362 os << "\\setotherlanguage";
2363 os << "{" << from_ascii(pl) << "}\n";
2367 // ... but before biblatex (see #7065)
2368 if ((features.mustProvide("biblatex")
2369 || features.isRequired("biblatex-chicago"))
2370 && !features.isProvided("biblatex-chicago")
2371 && !features.isProvided("biblatex-natbib")
2372 && !features.isProvided("natbib-internal")
2373 && !features.isProvided("natbib")
2374 && !features.isProvided("jurabib")) {
2375 // The biblatex-chicago package has a differing interface
2376 // it uses a wrapper package and loads styles via fixed options
2377 bool const chicago = features.isRequired("biblatex-chicago");
2380 os << "\\usepackage";
2381 if (!biblatex_bibstyle.empty()
2382 && (biblatex_bibstyle == biblatex_citestyle)
2384 opts = "style=" + biblatex_bibstyle;
2386 } else if (!chicago) {
2387 if (!biblatex_bibstyle.empty()) {
2388 opts = "bibstyle=" + biblatex_bibstyle;
2391 if (!biblatex_citestyle.empty()) {
2392 opts += delim + "citestyle=" + biblatex_citestyle;
2396 if (!multibib.empty() && multibib != "child") {
2397 opts += delim + "refsection=" + multibib;
2400 if (bibtexCommand() == "bibtex8"
2401 || prefixIs(bibtexCommand(), "bibtex8 ")) {
2402 opts += delim + "backend=bibtex8";
2404 } else if (bibtexCommand() == "bibtex"
2405 || prefixIs(bibtexCommand(), "bibtex ")) {
2406 opts += delim + "backend=bibtex";
2409 if (!bib_encoding.empty() && encodings.fromLyXName(bib_encoding)) {
2410 opts += delim + "bibencoding="
2411 + encodings.fromLyXName(bib_encoding)->latexName();
2414 if (!biblio_opts.empty())
2415 opts += delim + biblio_opts;
2417 os << "[" << opts << "]";
2419 os << "{biblatex-chicago}\n";
2421 os << "{biblatex}\n";
2425 // Load custom language package here
2426 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2427 if (lang_package == "default")
2428 os << from_utf8(lyxrc.language_custom_package);
2430 os << from_utf8(lang_package);
2434 // Since menukeys uses catoptions, which does some heavy changes on key-value options,
2435 // it is recommended to load menukeys as the last package (even after hyperref)
2436 if (features.isRequired("menukeys"))
2437 os << "\\usepackage{menukeys}\n";
2439 docstring const i18npreamble =
2440 features.getTClassI18nPreamble(use_babel, use_polyglossia,
2442 if (!i18npreamble.empty())
2443 os << i18npreamble + '\n';
2449 void BufferParams::useClassDefaults()
2451 DocumentClass const & tclass = documentClass();
2453 sides = tclass.sides();
2454 columns = tclass.columns();
2455 pagestyle = tclass.pagestyle();
2456 tablestyle = tclass.tablestyle();
2457 use_default_options = true;
2458 // Only if class has a ToC hierarchy
2459 if (tclass.hasTocLevels()) {
2460 secnumdepth = tclass.secnumdepth();
2461 tocdepth = tclass.tocdepth();
2466 bool BufferParams::hasClassDefaults() const
2468 DocumentClass const & tclass = documentClass();
2470 return sides == tclass.sides()
2471 && columns == tclass.columns()
2472 && pagestyle == tclass.pagestyle()
2473 && tablestyle == tclass.tablestyle()
2474 && use_default_options
2475 && secnumdepth == tclass.secnumdepth()
2476 && tocdepth == tclass.tocdepth();
2480 DocumentClass const & BufferParams::documentClass() const
2486 DocumentClassConstPtr BufferParams::documentClassPtr() const
2492 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2494 // evil, but this function is evil
2495 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2496 invalidateConverterCache();
2500 bool BufferParams::setBaseClass(string const & classname, string const & path)
2502 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2503 LayoutFileList & bcl = LayoutFileList::get();
2504 if (!bcl.haveClass(classname)) {
2506 bformat(_("The layout file:\n"
2508 "could not be found. A default textclass with default\n"
2509 "layouts will be used. LyX will not be able to produce\n"
2511 from_utf8(classname));
2512 frontend::Alert::error(_("Document class not found"), s);
2513 bcl.addEmptyClass(classname);
2516 bool const success = bcl[classname].load(path);
2519 bformat(_("Due to some error in it, the layout file:\n"
2521 "could not be loaded. A default textclass with default\n"
2522 "layouts will be used. LyX will not be able to produce\n"
2524 from_utf8(classname));
2525 frontend::Alert::error(_("Could not load class"), s);
2526 bcl.addEmptyClass(classname);
2529 pimpl_->baseClass_ = classname;
2530 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2535 LayoutFile const * BufferParams::baseClass() const
2537 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2538 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2544 LayoutFileIndex const & BufferParams::baseClassID() const
2546 return pimpl_->baseClass_;
2550 void BufferParams::makeDocumentClass(bool const clone)
2555 invalidateConverterCache();
2556 LayoutModuleList mods;
2557 for (auto const & mod : layout_modules_)
2558 mods.push_back(mod);
2560 doc_class_ = getDocumentClass(*baseClass(), mods, cite_engine_, clone);
2562 TextClass::ReturnValues success = TextClass::OK;
2563 if (!forced_local_layout_.empty())
2564 success = doc_class_->read(to_utf8(forced_local_layout_),
2566 if (!local_layout_.empty() &&
2567 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2568 success = doc_class_->read(to_utf8(local_layout_), TextClass::MODULE);
2569 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2570 docstring const msg = _("Error reading internal layout information");
2571 frontend::Alert::warning(_("Read Error"), msg);
2576 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2578 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2582 docstring BufferParams::getLocalLayout(bool forced) const
2585 return from_utf8(doc_class_->forcedLayouts());
2587 return local_layout_;
2591 void BufferParams::setLocalLayout(docstring const & layout, bool forced)
2594 forced_local_layout_ = layout;
2596 local_layout_ = layout;
2600 bool BufferParams::addLayoutModule(string const & modName)
2602 for (auto const & mod : layout_modules_)
2605 layout_modules_.push_back(modName);
2610 string BufferParams::bufferFormat() const
2612 return documentClass().outputFormat();
2616 bool BufferParams::isExportable(string const & format, bool need_viewable) const
2618 FormatList const & formats = exportableFormats(need_viewable);
2619 for (auto const & fmt : formats) {
2620 if (fmt->name() == format)
2627 FormatList const & BufferParams::exportableFormats(bool only_viewable) const
2629 FormatList & cached = only_viewable ?
2630 pimpl_->viewableFormatList : pimpl_->exportableFormatList;
2631 bool & valid = only_viewable ?
2632 pimpl_->isViewCacheValid : pimpl_->isExportCacheValid;
2636 vector<string> const backs = backends();
2637 set<string> excludes;
2638 if (useNonTeXFonts) {
2639 excludes.insert("latex");
2640 excludes.insert("pdflatex");
2641 } else if (inputenc != "ascii" && inputenc != "utf8-plain")
2642 // XeTeX with TeX fonts requires input encoding ascii (#10600).
2643 excludes.insert("xetex");
2644 FormatList result = theConverters().getReachable(backs[0], only_viewable,
2646 vector<string>::const_iterator it = backs.begin() + 1;
2647 for (; it != backs.end(); ++it) {
2648 FormatList r = theConverters().getReachable(*it, only_viewable,
2650 result.insert(result.end(), r.begin(), r.end());
2652 sort(result.begin(), result.end(), Format::formatSorter);
2659 vector<string> BufferParams::backends() const
2662 string const buffmt = bufferFormat();
2664 // FIXME: Don't hardcode format names here, but use a flag
2665 if (buffmt == "latex") {
2666 if (encoding().package() == Encoding::japanese)
2667 v.push_back("platex");
2669 if (!useNonTeXFonts) {
2670 v.push_back("pdflatex");
2671 v.push_back("latex");
2674 || inputenc == "ascii" || inputenc == "utf8-plain")
2675 v.push_back("xetex");
2676 v.push_back("luatex");
2677 v.push_back("dviluatex");
2680 string rbuffmt = buffmt;
2681 // If we use an OutputFormat in Japanese docs,
2682 // we need special format in order to get the path
2683 // via pLaTeX (#8823)
2684 if (documentClass().hasOutputFormat()
2685 && encoding().package() == Encoding::japanese)
2687 v.push_back(rbuffmt);
2690 v.push_back("xhtml");
2691 v.push_back("text");
2697 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2699 string const dformat = (format.empty() || format == "default") ?
2700 getDefaultOutputFormat() : format;
2701 DefaultFlavorCache::const_iterator it =
2702 default_flavors_.find(dformat);
2704 if (it != default_flavors_.end())
2707 OutputParams::FLAVOR result = OutputParams::LATEX;
2709 // FIXME It'd be better not to hardcode this, but to do
2710 // something with formats.
2711 if (dformat == "xhtml")
2712 result = OutputParams::HTML;
2713 else if (dformat == "text")
2714 result = OutputParams::TEXT;
2715 else if (dformat == "lyx")
2716 result = OutputParams::LYX;
2717 else if (dformat == "pdflatex")
2718 result = OutputParams::PDFLATEX;
2719 else if (dformat == "xetex")
2720 result = OutputParams::XETEX;
2721 else if (dformat == "luatex")
2722 result = OutputParams::LUATEX;
2723 else if (dformat == "dviluatex")
2724 result = OutputParams::DVILUATEX;
2726 // Try to determine flavor of default output format
2727 vector<string> backs = backends();
2728 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2729 // Get shortest path to format
2730 Graph::EdgePath path;
2731 for (auto const & bvar : backs) {
2732 Graph::EdgePath p = theConverters().getPath(bvar, dformat);
2733 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2738 result = theConverters().getFlavor(path);
2741 // cache this flavor
2742 default_flavors_[dformat] = result;
2747 string BufferParams::getDefaultOutputFormat() const
2749 if (!default_output_format.empty()
2750 && default_output_format != "default")
2751 return default_output_format;
2753 FormatList const & formats = exportableFormats(true);
2754 if (formats.empty())
2756 // return the first we find
2757 return formats.front()->name();
2759 if (encoding().package() == Encoding::japanese)
2760 return lyxrc.default_platex_view_format;
2762 return lyxrc.default_otf_view_format;
2763 return lyxrc.default_view_format;
2766 Font const BufferParams::getFont() const
2768 FontInfo f = documentClass().defaultfont();
2769 if (fonts_default_family == "rmdefault")
2770 f.setFamily(ROMAN_FAMILY);
2771 else if (fonts_default_family == "sfdefault")
2772 f.setFamily(SANS_FAMILY);
2773 else if (fonts_default_family == "ttdefault")
2774 f.setFamily(TYPEWRITER_FAMILY);
2775 return Font(f, language);
2779 InsetQuotesParams::QuoteStyle BufferParams::getQuoteStyle(string const & qs) const
2781 return quotesstyletranslator().find(qs);
2785 bool BufferParams::isLatex() const
2787 return documentClass().outputType() == LATEX;
2791 bool BufferParams::isLiterate() const
2793 return documentClass().outputType() == LITERATE;
2797 bool BufferParams::isDocBook() const
2799 return documentClass().outputType() == DOCBOOK;
2803 void BufferParams::readPreamble(Lexer & lex)
2805 if (lex.getString() != "\\begin_preamble")
2806 lyxerr << "Error (BufferParams::readPreamble):"
2807 "consistency check failed." << endl;
2809 preamble = lex.getLongString(from_ascii("\\end_preamble"));
2813 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2815 string const expected = forced ? "\\begin_forced_local_layout" :
2816 "\\begin_local_layout";
2817 if (lex.getString() != expected)
2818 lyxerr << "Error (BufferParams::readLocalLayout):"
2819 "consistency check failed." << endl;
2822 forced_local_layout_ =
2823 lex.getLongString(from_ascii("\\end_forced_local_layout"));
2825 local_layout_ = lex.getLongString(from_ascii("\\end_local_layout"));
2829 bool BufferParams::setLanguage(string const & lang)
2831 Language const *new_language = languages.getLanguage(lang);
2832 if (!new_language) {
2833 // Language lang was not found
2836 language = new_language;
2841 void BufferParams::readLanguage(Lexer & lex)
2843 if (!lex.next()) return;
2845 string const tmptok = lex.getString();
2847 // check if tmptok is part of tex_babel in tex-defs.h
2848 if (!setLanguage(tmptok)) {
2849 // Language tmptok was not found
2850 language = default_language;
2851 lyxerr << "Warning: Setting language `"
2852 << tmptok << "' to `" << language->lang()
2858 void BufferParams::readGraphicsDriver(Lexer & lex)
2863 string const tmptok = lex.getString();
2864 // check if tmptok is part of tex_graphics in tex_defs.h
2867 string const test = tex_graphics[n++];
2869 if (test == tmptok) {
2870 graphics_driver = tmptok;
2875 "Warning: graphics driver `$$Token' not recognized!\n"
2876 " Setting graphics driver to `default'.\n");
2877 graphics_driver = "default";
2884 void BufferParams::readBullets(Lexer & lex)
2889 int const index = lex.getInteger();
2891 int temp_int = lex.getInteger();
2892 user_defined_bullet(index).setFont(temp_int);
2893 temp_bullet(index).setFont(temp_int);
2895 user_defined_bullet(index).setCharacter(temp_int);
2896 temp_bullet(index).setCharacter(temp_int);
2898 user_defined_bullet(index).setSize(temp_int);
2899 temp_bullet(index).setSize(temp_int);
2903 void BufferParams::readBulletsLaTeX(Lexer & lex)
2905 // The bullet class should be able to read this.
2908 int const index = lex.getInteger();
2910 docstring const temp_str = lex.getDocString();
2912 user_defined_bullet(index).setText(temp_str);
2913 temp_bullet(index).setText(temp_str);
2917 void BufferParams::readModules(Lexer & lex)
2919 if (!lex.eatLine()) {
2920 lyxerr << "Error (BufferParams::readModules):"
2921 "Unexpected end of input." << endl;
2925 string mod = lex.getString();
2926 if (mod == "\\end_modules")
2928 addLayoutModule(mod);
2934 void BufferParams::readRemovedModules(Lexer & lex)
2936 if (!lex.eatLine()) {
2937 lyxerr << "Error (BufferParams::readRemovedModules):"
2938 "Unexpected end of input." << endl;
2942 string mod = lex.getString();
2943 if (mod == "\\end_removed_modules")
2945 removed_modules_.push_back(mod);
2948 // now we want to remove any removed modules that were previously
2949 // added. normally, that will be because default modules were added in
2950 // setBaseClass(), which gets called when \textclass is read at the
2951 // start of the read.
2952 for (auto const & rm : removed_modules_) {
2953 LayoutModuleList::iterator const mit = layout_modules_.begin();
2954 LayoutModuleList::iterator const men = layout_modules_.end();
2955 LayoutModuleList::iterator found = find(mit, men, rm);
2958 layout_modules_.erase(found);
2963 void BufferParams::readIncludeonly(Lexer & lex)
2965 if (!lex.eatLine()) {
2966 lyxerr << "Error (BufferParams::readIncludeonly):"
2967 "Unexpected end of input." << endl;
2971 string child = lex.getString();
2972 if (child == "\\end_includeonly")
2974 included_children_.push_back(child);
2980 string BufferParams::paperSizeName(PapersizePurpose purpose, string const & psize) const
2982 PAPER_SIZE ppsize = psize.empty() ? papersize : papersizetranslator().find(psize);
2985 if (documentClass().pagesize() == "default")
2986 // could be anything, so don't guess
2988 return paperSizeName(purpose, documentClass().pagesize());
2989 case PAPER_CUSTOM: {
2990 if (purpose == XDVI && !paperwidth.empty() &&
2991 !paperheight.empty()) {
2992 // heightxwidth<unit>
2993 string first = paperwidth;
2994 string second = paperheight;
2995 if (orientation == ORIENTATION_LANDSCAPE)
2998 return first.erase(first.length() - 2)
3004 // dvips and dvipdfm do not know this
3005 if (purpose == DVIPS || purpose == DVIPDFM)
3009 if (purpose == DVIPS || purpose == DVIPDFM)
3013 if (purpose == DVIPS || purpose == DVIPDFM)
3023 if (purpose == DVIPS || purpose == DVIPDFM)
3027 if (purpose == DVIPS || purpose == DVIPDFM)
3031 if (purpose == DVIPS || purpose == DVIPDFM)
3035 if (purpose == DVIPS || purpose == DVIPDFM)
3039 if (purpose == DVIPS || purpose == DVIPDFM)
3043 // dvipdfm does not know this
3044 if (purpose == DVIPDFM)
3048 if (purpose == DVIPDFM)
3052 if (purpose == DVIPS || purpose == DVIPDFM)
3056 if (purpose == DVIPS || purpose == DVIPDFM)
3060 if (purpose == DVIPS || purpose == DVIPDFM)
3064 if (purpose == DVIPS || purpose == DVIPDFM)
3068 if (purpose == DVIPS || purpose == DVIPDFM)
3072 if (purpose == DVIPS || purpose == DVIPDFM)
3076 if (purpose == DVIPS || purpose == DVIPDFM)
3080 if (purpose == DVIPS || purpose == DVIPDFM)
3084 if (purpose == DVIPS || purpose == DVIPDFM)
3088 if (purpose == DVIPS || purpose == DVIPDFM)
3092 if (purpose == DVIPS || purpose == DVIPDFM)
3096 if (purpose == DVIPS || purpose == DVIPDFM)
3100 if (purpose == DVIPS || purpose == DVIPDFM)
3104 if (purpose == DVIPS || purpose == DVIPDFM)
3108 if (purpose == DVIPS || purpose == DVIPDFM)
3111 case PAPER_USEXECUTIVE:
3112 // dvipdfm does not know this
3113 if (purpose == DVIPDFM)
3118 case PAPER_USLETTER:
3120 if (purpose == XDVI)
3127 string const BufferParams::dvips_options() const
3131 // If the class loads the geometry package, we do not know which
3132 // paper size is used, since we do not set it (bug 7013).
3133 // Therefore we must not specify any argument here.
3134 // dvips gets the correct paper size via DVI specials in this case
3135 // (if the class uses the geometry package correctly).
3136 if (documentClass().provides("geometry"))
3140 && papersize == PAPER_CUSTOM
3141 && !lyxrc.print_paper_dimension_flag.empty()
3142 && !paperwidth.empty()
3143 && !paperheight.empty()) {
3144 // using a custom papersize
3145 result = lyxrc.print_paper_dimension_flag;
3146 result += ' ' + paperwidth;
3147 result += ',' + paperheight;
3149 string const paper_option = paperSizeName(DVIPS);
3150 if (!paper_option.empty() && (paper_option != "letter" ||
3151 orientation != ORIENTATION_LANDSCAPE)) {
3152 // dvips won't accept -t letter -t landscape.
3153 // In all other cases, include the paper size
3155 result = lyxrc.print_paper_flag;
3156 result += ' ' + paper_option;
3159 if (orientation == ORIENTATION_LANDSCAPE &&
3160 papersize != PAPER_CUSTOM)
3161 result += ' ' + lyxrc.print_landscape_flag;
3166 string const BufferParams::main_font_encoding() const
3168 if (font_encodings().empty()) {
3169 if (ascii_lowercase(language->fontenc(*this)) == "none")
3173 return font_encodings().back();
3177 vector<string> const BufferParams::font_encodings() const
3179 string doc_fontenc = (fontenc == "auto") ? string() : fontenc;
3181 vector<string> fontencs;
3183 // "default" means "no explicit font encoding"
3184 if (doc_fontenc != "default") {
3185 if (!doc_fontenc.empty())
3186 // If we have a custom setting, we use only that!
3187 return getVectorFromString(doc_fontenc);
3188 if (!language->fontenc(*this).empty()
3189 && ascii_lowercase(language->fontenc(*this)) != "none") {
3190 vector<string> fencs = getVectorFromString(language->fontenc(*this));
3191 for (auto & fe : fencs) {
3192 if (find(fontencs.begin(), fontencs.end(), fe) == fontencs.end())
3193 fontencs.push_back(fe);
3202 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
3204 // suppress the babel call if there is no BabelName defined
3205 // for the document language in the lib/languages file and if no
3206 // other languages are used (lang_opts is then empty)
3207 if (lang_opts.empty())
3209 // The prefs may require the languages to
3210 // be submitted to babel itself (not the class).
3212 return "\\usepackage[" + lang_opts + "]{babel}";
3213 return "\\usepackage{babel}";
3217 docstring BufferParams::getGraphicsDriver(string const & package) const
3221 if (package == "geometry") {
3222 if (graphics_driver == "dvips"
3223 || graphics_driver == "dvipdfm"
3224 || graphics_driver == "pdftex"
3225 || graphics_driver == "vtex")
3226 result = from_ascii(graphics_driver);
3227 else if (graphics_driver == "dvipdfmx")
3228 result = from_ascii("dvipdfm");
3235 void BufferParams::writeEncodingPreamble(otexstream & os,
3236 LaTeXFeatures & features) const
3238 // With no-TeX fonts we use utf8-plain without encoding package.
3242 if (inputenc == "auto-legacy") {
3243 string const doc_encoding =
3244 language->encoding()->latexName();
3245 Encoding::Package const package =
3246 language->encoding()->package();
3248 // Create list of inputenc options:
3249 set<string> encoding_set;
3250 // luainputenc fails with more than one encoding
3251 if (features.runparams().flavor != OutputParams::LUATEX
3252 && features.runparams().flavor != OutputParams::DVILUATEX)
3253 // list all input encodings used in the document
3254 encoding_set = features.getEncodingSet(doc_encoding);
3256 // The "japanese" babel-language requires the pLaTeX engine
3257 // which conflicts with "inputenc".
3258 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
3259 if ((!encoding_set.empty() || package == Encoding::inputenc)
3260 && !features.isRequired("japanese")
3261 && !features.isProvided("inputenc")) {
3262 os << "\\usepackage[";
3263 set<string>::const_iterator it = encoding_set.begin();
3264 set<string>::const_iterator const end = encoding_set.end();
3266 os << from_ascii(*it);
3269 for (; it != end; ++it)
3270 os << ',' << from_ascii(*it);
3271 if (package == Encoding::inputenc) {
3272 if (!encoding_set.empty())
3274 os << from_ascii(doc_encoding);
3276 if (features.runparams().flavor == OutputParams::LUATEX
3277 || features.runparams().flavor == OutputParams::DVILUATEX)
3278 os << "]{luainputenc}\n";
3280 os << "]{inputenc}\n";
3282 } else if (inputenc != "auto-legacy-plain") {
3283 switch (encoding().package()) {
3284 case Encoding::none:
3286 case Encoding::japanese:
3287 if (encoding().iconvName() != "UTF-8"
3288 && !features.runparams().isFullUnicode())
3289 // don't default to [utf8]{inputenc} with TeXLive >= 18
3290 os << "\\ifdefined\\UseRawInputEncoding\n"
3291 << " \\UseRawInputEncoding\\fi\n";
3293 case Encoding::inputenc:
3294 // do not load inputenc if japanese is used
3295 // or if the class provides inputenc
3296 if (features.isRequired("japanese")
3297 || features.isProvided("inputenc"))
3299 os << "\\usepackage[" << from_ascii(encoding().latexName());
3300 if (features.runparams().flavor == OutputParams::LUATEX
3301 || features.runparams().flavor == OutputParams::DVILUATEX)
3302 os << "]{luainputenc}\n";
3304 os << "]{inputenc}\n";
3308 if (inputenc == "auto-legacy-plain" || features.isRequired("japanese")) {
3309 // don't default to [utf8]{inputenc} with TeXLive >= 18
3310 os << "\\ifdefined\\UseRawInputEncoding\n";
3311 os << " \\UseRawInputEncoding\\fi\n";
3316 string const BufferParams::parseFontName(string const & name) const
3318 string mangled = name;
3319 size_t const idx = mangled.find('[');
3320 if (idx == string::npos || idx == 0)
3323 return mangled.substr(0, idx - 1);
3327 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3329 if (fontsRoman() == "default" && fontsSans() == "default"
3330 && fontsTypewriter() == "default"
3331 && (fontsMath() == "default" || fontsMath() == "auto"))
3337 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3338 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3339 * Mapping=tex-text option assures TeX ligatures (such as "--")
3340 * are resolved. Note that tt does not use these ligatures.
3342 * -- add more GUI options?
3343 * -- add more fonts (fonts for other scripts)
3344 * -- if there's a way to find out if a font really supports
3345 * OldStyle, enable/disable the widget accordingly.
3347 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3348 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3349 // However, until v.2 (2010/07/11) fontspec only knew
3350 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3351 // was introduced for both XeTeX and LuaTeX (LuaTeX
3352 // didn't understand "Mapping=tex-text", while XeTeX
3353 // understood both. With most recent versions, both
3354 // variants are understood by both engines. However,
3355 // we want to provide support for at least TeXLive 2009
3356 // (for XeTeX; LuaTeX is only supported as of v.2)
3357 // As of 2017/11/03, Babel has its own higher-level
3358 // interface on top of fontspec that is to be used.
3359 bool const babelfonts = features.useBabel()
3360 && features.isAvailable("babel-2017/11/03");
3361 string const texmapping =
3362 (features.runparams().flavor == OutputParams::XETEX) ?
3363 "Mapping=tex-text" : "Ligatures=TeX";
3364 if (fontsRoman() != "default") {
3366 os << "\\babelfont{rm}[";
3368 os << "\\setmainfont[";
3369 if (!font_roman_opts.empty())
3370 os << font_roman_opts << ',';
3372 if (fonts_roman_osf)
3373 os << ",Numbers=OldStyle";
3374 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3376 if (fontsSans() != "default") {
3377 string const sans = parseFontName(fontsSans());
3378 if (fontsSansScale() != 100) {
3380 os << "\\babelfont{sf}";
3382 os << "\\setsansfont";
3384 << float(fontsSansScale()) / 100 << ',';
3386 os << "Numbers=OldStyle,";
3387 if (!font_sans_opts.empty())
3388 os << font_sans_opts << ',';
3389 os << texmapping << "]{"
3393 os << "\\babelfont{sf}[";
3395 os << "\\setsansfont[";
3397 os << "Numbers=OldStyle,";
3398 if (!font_sans_opts.empty())
3399 os << font_sans_opts << ',';
3400 os << texmapping << "]{"
3404 if (fontsTypewriter() != "default") {
3405 string const mono = parseFontName(fontsTypewriter());
3406 if (fontsTypewriterScale() != 100) {
3408 os << "\\babelfont{tt}";
3410 os << "\\setmonofont";
3412 << float(fontsTypewriterScale()) / 100;
3413 if (fonts_typewriter_osf)
3414 os << ",Numbers=OldStyle";
3415 if (!font_typewriter_opts.empty())
3416 os << ',' << font_typewriter_opts;
3421 os << "\\babelfont{tt}";
3423 os << "\\setmonofont";
3424 if (!font_typewriter_opts.empty() || fonts_typewriter_osf) {
3426 if (fonts_typewriter_osf)
3427 os << "Numbers=OldStyle";
3428 if (!font_typewriter_opts.empty()) {
3429 if (fonts_typewriter_osf)
3431 os << font_typewriter_opts;
3435 os << '{' << mono << "}\n";
3442 bool const ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1");
3443 bool const dryrun = features.runparams().dryrun;
3444 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3445 bool const nomath = (fontsMath() == "default");
3448 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3449 dryrun, ot1, complete, fonts_expert_sc, fonts_roman_osf,
3450 nomath, font_roman_opts);
3453 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3454 dryrun, ot1, complete, fonts_expert_sc, fonts_sans_osf,
3455 nomath, font_sans_opts, fontsSansScale());
3457 // MONOSPACED/TYPEWRITER
3458 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3459 dryrun, ot1, complete, fonts_expert_sc, fonts_typewriter_osf,
3460 nomath, font_typewriter_opts, fontsTypewriterScale());
3463 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3464 dryrun, ot1, complete, fonts_expert_sc, fonts_roman_osf,
3471 Encoding const & BufferParams::encoding() const
3473 // Main encoding for LaTeX output.
3475 return *(encodings.fromLyXName("utf8-plain"));
3476 if (inputenc == "auto-legacy" || inputenc == "auto-legacy-plain")
3477 return *language->encoding();
3478 if (inputenc == "utf8" && language->lang() == "japanese")
3479 return *(encodings.fromLyXName("utf8-platex"));
3480 Encoding const * const enc = encodings.fromLyXName(inputenc);
3483 LYXERR0("Unknown inputenc value `" << inputenc
3484 << "'. Using `auto' instead.");
3485 return *language->encoding();
3489 string const & BufferParams::defaultBiblioStyle() const
3491 if (!biblio_style.empty())
3492 return biblio_style;
3494 map<string, string> const & bs = documentClass().defaultBiblioStyle();
3495 auto cit = bs.find(theCiteEnginesList.getTypeAsString(citeEngineType()));
3496 if (cit != bs.end())
3499 return empty_string();
3503 bool const & BufferParams::fullAuthorList() const
3505 return documentClass().fullAuthorList();
3509 string BufferParams::getCiteAlias(string const & s) const
3511 vector<string> commands =
3512 documentClass().citeCommands(citeEngineType());
3513 // If it is a real command, don't treat it as an alias
3514 if (find(commands.begin(), commands.end(), s) != commands.end())
3516 map<string,string> aliases = documentClass().citeCommandAliases();
3517 if (aliases.find(s) != aliases.end())
3523 vector<string> BufferParams::citeCommands() const
3525 static CitationStyle const default_style;
3526 vector<string> commands =
3527 documentClass().citeCommands(citeEngineType());
3528 if (commands.empty())
3529 commands.push_back(default_style.name);
3534 vector<CitationStyle> BufferParams::citeStyles() const
3536 static CitationStyle const default_style;
3537 vector<CitationStyle> styles =
3538 documentClass().citeStyles(citeEngineType());
3540 styles.push_back(default_style);
3545 string const BufferParams::bibtexCommand() const
3547 // Return document-specific setting if available
3548 if (bibtex_command != "default")
3549 return bibtex_command;
3551 // If we have "default" in document settings, consult the prefs
3552 // 1. Japanese (uses a specific processor)
3553 if (encoding().package() == Encoding::japanese) {
3554 if (lyxrc.jbibtex_command != "automatic")
3555 // Return the specified program, if "automatic" is not set
3556 return lyxrc.jbibtex_command;
3557 else if (!useBiblatex()) {
3558 // With classic BibTeX, return pbibtex, jbibtex, bibtex
3559 if (lyxrc.jbibtex_alternatives.find("pbibtex") != lyxrc.jbibtex_alternatives.end())
3561 if (lyxrc.jbibtex_alternatives.find("jbibtex") != lyxrc.jbibtex_alternatives.end())
3566 // 2. All other languages
3567 else if (lyxrc.bibtex_command != "automatic")
3568 // Return the specified program, if "automatic" is not set
3569 return lyxrc.bibtex_command;
3571 // 3. Automatic: find the most suitable for the current cite framework
3572 if (useBiblatex()) {
3573 // For Biblatex, we prefer biber (also for Japanese)
3574 // and fall back to bibtex8 and, as last resort, bibtex
3575 if (lyxrc.bibtex_alternatives.find("biber") != lyxrc.bibtex_alternatives.end())
3577 else if (lyxrc.bibtex_alternatives.find("bibtex8") != lyxrc.bibtex_alternatives.end())
3584 bool BufferParams::useBiblatex() const
3586 return theCiteEnginesList[citeEngine()]->getCiteFramework() == "biblatex";
3590 void BufferParams::invalidateConverterCache() const
3592 pimpl_->isExportCacheValid = false;
3593 pimpl_->isViewCacheValid = false;
3597 // We shouldn't need to reset the params here, since anything
3598 // we need will be recopied.
3599 void BufferParams::copyForAdvFR(const BufferParams & bp)
3601 string const & lang = bp.language->lang();
3603 layout_modules_ = bp.layout_modules_;
3604 string const & doc_class = bp.documentClass().name();
3605 setBaseClass(doc_class);
3609 void BufferParams::setBibFileEncoding(string const & file, string const & enc)
3611 bib_encodings[file] = enc;
3615 string const BufferParams::bibFileEncoding(string const & file) const
3617 if (bib_encodings.find(file) == bib_encodings.end())
3619 return bib_encodings.find(file)->second;