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 docbook_table_output = HTMLTable;
475 display_pixel_ratio = 1.0;
477 shell_escape = false;
483 // map current author
484 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
488 docstring BufferParams::B_(string const & l10n) const
490 LASSERT(language, return from_utf8(l10n));
491 return getMessages(language->code()).get(l10n);
495 BufferParams::Package BufferParams::use_package(std::string const & p) const
497 PackageMap::const_iterator it = use_packages.find(p);
498 if (it == use_packages.end())
504 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
510 map<string, string> const & BufferParams::auto_packages()
512 static map<string, string> packages;
513 if (packages.empty()) {
514 // We could have a race condition here that two threads
515 // discover an empty map at the same time and want to fill
516 // it, but that is no problem, since the same contents is
517 // filled in twice then. Having the locker inside the
518 // packages.empty() condition has the advantage that we
519 // don't need the mutex overhead for simple reading.
521 Mutex::Locker locker(&mutex);
522 // adding a package here implies a file format change!
523 packages["amsmath"] =
524 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
525 packages["amssymb"] =
526 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
528 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
530 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
531 packages["mathdots"] =
532 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
533 packages["mathtools"] =
534 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
536 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
537 packages["stackrel"] =
538 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
539 packages["stmaryrd"] =
540 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");
541 packages["undertilde"] =
542 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
548 bool BufferParams::useBibtopic() const
552 return (use_bibtopic || (!multibib.empty() && multibib != "child"));
556 AuthorList & BufferParams::authors()
558 return pimpl_->authorlist;
562 AuthorList const & BufferParams::authors() const
564 return pimpl_->authorlist;
568 void BufferParams::addAuthor(Author a)
570 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
574 BranchList & BufferParams::branchlist()
576 return pimpl_->branchlist;
580 BranchList const & BufferParams::branchlist() const
582 return pimpl_->branchlist;
586 IndicesList & BufferParams::indiceslist()
588 return pimpl_->indiceslist;
592 IndicesList const & BufferParams::indiceslist() const
594 return pimpl_->indiceslist;
598 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
600 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
601 return pimpl_->temp_bullets[index];
605 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
607 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
608 return pimpl_->temp_bullets[index];
612 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
614 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
615 return pimpl_->user_defined_bullets[index];
619 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
621 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
622 return pimpl_->user_defined_bullets[index];
626 Spacing & BufferParams::spacing()
628 return pimpl_->spacing;
632 Spacing const & BufferParams::spacing() const
634 return pimpl_->spacing;
638 PDFOptions & BufferParams::pdfoptions()
640 return pimpl_->pdfoptions;
644 PDFOptions const & BufferParams::pdfoptions() const
646 return pimpl_->pdfoptions;
650 Length const & BufferParams::getMathIndent() const
652 return pimpl_->mathindent;
656 void BufferParams::setMathIndent(Length const & indent)
658 pimpl_->mathindent = indent;
662 Length const & BufferParams::getParIndent() const
664 return pimpl_->parindent;
668 void BufferParams::setParIndent(Length const & indent)
670 pimpl_->parindent = indent;
674 VSpace const & BufferParams::getDefSkip() const
676 return pimpl_->defskip;
680 void BufferParams::setDefSkip(VSpace const & vs)
682 // DEFSKIP will cause an infinite loop
683 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
684 pimpl_->defskip = vs;
688 BufferParams::MathNumber BufferParams::getMathNumber() const
690 if (math_numbering_side != DEFAULT)
691 return math_numbering_side;
692 // FIXME: do not hardcode language here
693 else if (language->lang() == "arabic_arabi"
694 || documentClass().provides("leqno"))
701 string BufferParams::readToken(Lexer & lex, string const & token,
702 FileName const & filepath)
706 if (token == "\\textclass") {
708 string const classname = lex.getString();
709 // if there exists a local layout file, ignore the system one
710 // NOTE: in this case, the textclass (.cls file) is assumed to
713 LayoutFileList & bcl = LayoutFileList::get();
714 if (!filepath.empty()) {
715 // If classname is an absolute path, the document is
716 // using a local layout file which could not be accessed
717 // by a relative path. In this case the path is correct
718 // even if the document was moved to a different
719 // location. However, we will have a problem if the
720 // document was generated on a different platform.
721 bool isabsolute = FileName::isAbsolute(classname);
722 string const classpath = onlyPath(classname);
723 string const path = isabsolute ? classpath
724 : FileName(addPath(filepath.absFileName(),
725 classpath)).realPath();
726 string const oldpath = isabsolute ? string()
727 : FileName(addPath(origin, classpath)).realPath();
728 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
730 // that returns non-empty if a "local" layout file is found.
732 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
733 from_utf8(filepath.absFileName())));
736 setBaseClass(onlyFileName(tcp));
738 setBaseClass(onlyFileName(classname));
739 // We assume that a tex class exists for local or unknown
740 // layouts so this warning, will only be given for system layouts.
741 if (!baseClass()->isTeXClassAvailable()) {
742 docstring const desc =
743 translateIfPossible(from_utf8(baseClass()->description()));
744 docstring const prereqs =
745 from_utf8(baseClass()->prerequisites());
746 docstring const msg =
747 bformat(_("The selected document class\n"
749 "requires external files that are not available.\n"
750 "The document class can still be used, but the\n"
751 "document cannot be compiled until the following\n"
752 "prerequisites are installed:\n"
754 "See section 3.1.2.2 (Class Availability) of the\n"
755 "User's Guide for more information."), desc, prereqs);
756 frontend::Alert::warning(_("Document class not available"),
759 } else if (token == "\\save_transient_properties") {
760 lex >> save_transient_properties;
761 } else if (token == "\\origin") {
763 origin = lex.getString();
764 string const sysdirprefix = "/systemlyxdir/";
765 if (prefixIs(origin, sysdirprefix)) {
767 if (inSystemDir(filepath, docsys))
768 origin.replace(0, sysdirprefix.length() - 1, docsys);
770 origin.replace(0, sysdirprefix.length() - 1,
771 package().system_support().absFileName());
773 } else if (token == "\\begin_preamble") {
775 } else if (token == "\\begin_local_layout") {
776 readLocalLayout(lex, false);
777 } else if (token == "\\begin_forced_local_layout") {
778 readLocalLayout(lex, true);
779 } else if (token == "\\begin_modules") {
781 } else if (token == "\\begin_removed_modules") {
782 readRemovedModules(lex);
783 } else if (token == "\\begin_includeonly") {
784 readIncludeonly(lex);
785 } else if (token == "\\maintain_unincluded_children") {
789 maintain_unincluded_children = CM_None;
790 else if (tmp == "mostly")
791 maintain_unincluded_children = CM_Mostly;
792 else if (tmp == "strict")
793 maintain_unincluded_children = CM_Strict;
794 } else if (token == "\\options") {
796 options = lex.getString();
797 } else if (token == "\\use_default_options") {
798 lex >> use_default_options;
799 } else if (token == "\\master") {
801 master = lex.getString();
802 if (!filepath.empty() && FileName::isAbsolute(origin)) {
803 bool const isabs = FileName::isAbsolute(master);
804 FileName const abspath(isabs ? master : origin + master);
805 bool const moved = filepath != FileName(origin);
806 if (moved && abspath.exists()) {
807 docstring const path = isabs
809 : from_utf8(abspath.realPath());
810 docstring const refpath =
811 from_utf8(filepath.absFileName());
812 master = to_utf8(makeRelPath(path, refpath));
815 } else if (token == "\\suppress_date") {
816 lex >> suppress_date;
817 } else if (token == "\\justification") {
818 lex >> justification;
819 } else if (token == "\\language") {
821 } else if (token == "\\language_package") {
823 lang_package = lex.getString();
824 } else if (token == "\\inputencoding") {
826 } else if (token == "\\graphics") {
827 readGraphicsDriver(lex);
828 } else if (token == "\\default_output_format") {
829 lex >> default_output_format;
830 } else if (token == "\\bibtex_command") {
832 bibtex_command = lex.getString();
833 } else if (token == "\\index_command") {
835 index_command = lex.getString();
836 } else if (token == "\\fontencoding") {
838 fontenc = lex.getString();
839 } else if (token == "\\font_roman") {
840 lex >> fonts_roman[0];
841 lex >> fonts_roman[1];
842 } else if (token == "\\font_sans") {
843 lex >> fonts_sans[0];
844 lex >> fonts_sans[1];
845 } else if (token == "\\font_typewriter") {
846 lex >> fonts_typewriter[0];
847 lex >> fonts_typewriter[1];
848 } else if (token == "\\font_math") {
849 lex >> fonts_math[0];
850 lex >> fonts_math[1];
851 } else if (token == "\\font_default_family") {
852 lex >> fonts_default_family;
853 } else if (token == "\\use_non_tex_fonts") {
854 lex >> useNonTeXFonts;
855 } else if (token == "\\font_sc") {
856 lex >> fonts_expert_sc;
857 } else if (token == "\\font_roman_osf") {
858 lex >> fonts_roman_osf;
859 } else if (token == "\\font_sans_osf") {
860 lex >> fonts_sans_osf;
861 } else if (token == "\\font_typewriter_osf") {
862 lex >> fonts_typewriter_osf;
863 } else if (token == "\\font_roman_opts") {
864 lex >> font_roman_opts;
865 } else if (token == "\\font_sf_scale") {
866 lex >> fonts_sans_scale[0];
867 lex >> fonts_sans_scale[1];
868 } else if (token == "\\font_sans_opts") {
869 lex >> font_sans_opts;
870 } else if (token == "\\font_tt_scale") {
871 lex >> fonts_typewriter_scale[0];
872 lex >> fonts_typewriter_scale[1];
873 } else if (token == "\\font_typewriter_opts") {
874 lex >> font_typewriter_opts;
875 } else if (token == "\\font_cjk") {
877 } else if (token == "\\use_microtype") {
878 lex >> use_microtype;
879 } else if (token == "\\use_dash_ligatures") {
880 lex >> use_dash_ligatures;
881 } else if (token == "\\paragraph_separation") {
884 paragraph_separation = parseptranslator().find(parsep);
885 } else if (token == "\\paragraph_indentation") {
887 string parindent = lex.getString();
888 if (parindent == "default")
889 pimpl_->parindent = Length();
891 pimpl_->parindent = Length(parindent);
892 } else if (token == "\\defskip") {
894 string const defskip = lex.getString();
895 pimpl_->defskip = VSpace(defskip);
896 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
898 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
899 } else if (token == "\\is_math_indent") {
900 lex >> is_math_indent;
901 } else if (token == "\\math_indentation") {
903 string mathindent = lex.getString();
904 if (mathindent == "default")
905 pimpl_->mathindent = Length();
907 pimpl_->mathindent = Length(mathindent);
908 } else if (token == "\\math_numbering_side") {
912 math_numbering_side = LEFT;
913 else if (tmp == "right")
914 math_numbering_side = RIGHT;
916 math_numbering_side = DEFAULT;
917 } else if (token == "\\quotes_style") {
920 quotes_style = quotesstyletranslator().find(qstyle);
921 } else if (token == "\\dynamic_quotes") {
922 lex >> dynamic_quotes;
923 } else if (token == "\\papersize") {
926 papersize = papersizetranslator().find(ppsize);
927 } else if (token == "\\use_geometry") {
929 } else if (token == "\\use_package") {
934 use_package(package, packagetranslator().find(use));
935 } else if (token == "\\cite_engine") {
937 cite_engine_ = lex.getString();
938 } else if (token == "\\cite_engine_type") {
941 cite_engine_type_ = theCiteEnginesList.getType(engine_type);
942 } else if (token == "\\biblio_style") {
944 biblio_style = lex.getString();
945 } else if (token == "\\biblio_options") {
947 biblio_opts = trim(lex.getString());
948 } else if (token == "\\biblatex_bibstyle") {
950 biblatex_bibstyle = trim(lex.getString());
951 } else if (token == "\\biblatex_citestyle") {
953 biblatex_citestyle = trim(lex.getString());
954 } else if (token == "\\use_bibtopic") {
956 } else if (token == "\\multibib") {
958 } else if (token == "\\use_indices") {
960 } else if (token == "\\tracking_changes") {
961 lex >> track_changes;
962 } else if (token == "\\output_changes") {
963 lex >> output_changes;
964 } else if (token == "\\change_bars") {
966 } else if (token == "\\postpone_fragile_content") {
967 lex >> postpone_fragile_content;
968 } else if (token == "\\branch") {
970 docstring branch = lex.getDocString();
971 branchlist().add(branch);
974 string const tok = lex.getString();
975 if (tok == "\\end_branch")
977 Branch * branch_ptr = branchlist().find(branch);
978 if (tok == "\\selected") {
981 branch_ptr->setSelected(lex.getInteger());
983 if (tok == "\\filename_suffix") {
986 branch_ptr->setFileNameSuffix(lex.getInteger());
988 if (tok == "\\color") {
990 string color = lex.getString();
992 branch_ptr->setColor(color);
993 // Update also the Color table:
995 color = lcolor.getX11Name(Color_background);
997 lcolor.setColor(to_utf8(branch), color);
1000 } else if (token == "\\index") {
1002 docstring index = lex.getDocString();
1004 indiceslist().add(index);
1007 string const tok = lex.getString();
1008 if (tok == "\\end_index")
1010 Index * index_ptr = indiceslist().find(index);
1011 if (tok == "\\shortcut") {
1013 shortcut = lex.getDocString();
1015 index_ptr->setShortcut(shortcut);
1017 if (tok == "\\color") {
1019 string color = lex.getString();
1021 index_ptr->setColor(color);
1022 // Update also the Color table:
1023 if (color == "none")
1024 color = lcolor.getX11Name(Color_background);
1026 if (!shortcut.empty())
1027 lcolor.setColor(to_utf8(shortcut), color);
1030 } else if (token == "\\author") {
1032 istringstream ss(lex.getString());
1036 } else if (token == "\\paperorientation") {
1039 orientation = paperorientationtranslator().find(orient);
1040 } else if (token == "\\backgroundcolor") {
1042 backgroundcolor = lyx::rgbFromHexName(lex.getString());
1043 isbackgroundcolor = true;
1044 } else if (token == "\\fontcolor") {
1046 fontcolor = lyx::rgbFromHexName(lex.getString());
1048 } else if (token == "\\notefontcolor") {
1050 string color = lex.getString();
1051 notefontcolor = lyx::rgbFromHexName(color);
1052 lcolor.setColor("notefontcolor", color);
1053 } else if (token == "\\boxbgcolor") {
1055 string color = lex.getString();
1056 boxbgcolor = lyx::rgbFromHexName(color);
1057 lcolor.setColor("boxbgcolor", color);
1058 } else if (token == "\\paperwidth") {
1060 } else if (token == "\\paperheight") {
1062 } else if (token == "\\leftmargin") {
1064 } else if (token == "\\topmargin") {
1066 } else if (token == "\\rightmargin") {
1068 } else if (token == "\\bottommargin") {
1069 lex >> bottommargin;
1070 } else if (token == "\\headheight") {
1072 } else if (token == "\\headsep") {
1074 } else if (token == "\\footskip") {
1076 } else if (token == "\\columnsep") {
1078 } else if (token == "\\paperfontsize") {
1080 } else if (token == "\\papercolumns") {
1082 } else if (token == "\\listings_params") {
1085 listings_params = InsetListingsParams(par).params();
1086 } else if (token == "\\papersides") {
1089 sides = sidestranslator().find(psides);
1090 } else if (token == "\\paperpagestyle") {
1092 } else if (token == "\\tablestyle") {
1094 } else if (token == "\\bullet") {
1096 } else if (token == "\\bulletLaTeX") {
1097 readBulletsLaTeX(lex);
1098 } else if (token == "\\secnumdepth") {
1100 } else if (token == "\\tocdepth") {
1102 } else if (token == "\\spacing") {
1106 if (nspacing == "other") {
1109 spacing().set(spacetranslator().find(nspacing), tmp_val);
1110 } else if (token == "\\float_placement") {
1111 lex >> float_placement;
1112 } else if (token == "\\float_alignment") {
1113 lex >> float_alignment;
1115 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
1116 string toktmp = pdfoptions().readToken(lex, token);
1117 if (!toktmp.empty()) {
1118 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
1122 } else if (token == "\\html_math_output") {
1125 html_math_output = static_cast<MathOutput>(temp);
1126 } else if (token == "\\html_be_strict") {
1127 lex >> html_be_strict;
1128 } else if (token == "\\html_css_as_file") {
1129 lex >> html_css_as_file;
1130 } else if (token == "\\html_math_img_scale") {
1131 lex >> html_math_img_scale;
1132 } else if (token == "\\html_latex_start") {
1134 html_latex_start = lex.getString();
1135 } else if (token == "\\html_latex_end") {
1137 html_latex_end = lex.getString();
1138 } else if (token == "\\docbook_table_output") {
1141 docbook_table_output = static_cast<TableOutput>(temp);
1142 } else if (token == "\\output_sync") {
1144 } else if (token == "\\output_sync_macro") {
1145 lex >> output_sync_macro;
1146 } else if (token == "\\use_refstyle") {
1147 lex >> use_refstyle;
1148 } else if (token == "\\use_minted") {
1150 } else if (token == "\\use_lineno") {
1152 } else if (token == "\\lineno_options") {
1154 lineno_opts = trim(lex.getString());
1156 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1166 // Quote argument if it contains spaces
1167 string quoteIfNeeded(string const & str) {
1168 if (contains(str, ' '))
1169 return "\"" + str + "\"";
1175 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1177 // The top of the file is written by the buffer.
1178 // Prints out the buffer info into the .lyx file given by file
1180 os << "\\save_transient_properties "
1181 << convert<string>(save_transient_properties) << '\n';
1183 // the document directory (must end with a path separator)
1184 // realPath() is used to resolve symlinks, while addPath(..., "")
1185 // ensures a trailing path separator.
1187 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1188 string const sysdir = inSystemDir(FileName(filepath), docsys) ? docsys
1189 : addPath(package().system_support().realPath(), "");
1190 string const relpath =
1191 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1192 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1193 filepath = addPath("/systemlyxdir", relpath);
1194 else if (!save_transient_properties || !lyxrc.save_origin)
1195 filepath = "unavailable";
1196 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1199 os << "\\textclass "
1200 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1201 baseClass()->name()), "layout"))
1204 // then the preamble
1205 if (!preamble.empty()) {
1206 // remove '\n' from the end of preamble
1207 docstring const tmppreamble = rtrim(preamble, "\n");
1208 os << "\\begin_preamble\n"
1209 << to_utf8(tmppreamble)
1210 << "\n\\end_preamble\n";
1214 if (!options.empty()) {
1215 os << "\\options " << options << '\n';
1218 // use the class options defined in the layout?
1219 os << "\\use_default_options "
1220 << convert<string>(use_default_options) << "\n";
1222 // the master document
1223 if (!master.empty()) {
1224 os << "\\master " << master << '\n';
1228 if (!removed_modules_.empty()) {
1229 os << "\\begin_removed_modules" << '\n';
1230 for (auto const & mod : removed_modules_)
1232 os << "\\end_removed_modules" << '\n';
1236 if (!layout_modules_.empty()) {
1237 os << "\\begin_modules" << '\n';
1238 for (auto const & mod : layout_modules_)
1240 os << "\\end_modules" << '\n';
1244 if (!included_children_.empty()) {
1245 os << "\\begin_includeonly" << '\n';
1246 for (auto const & c : included_children_)
1248 os << "\\end_includeonly" << '\n';
1251 switch (maintain_unincluded_children) {
1262 os << "\\maintain_unincluded_children " << muc << '\n';
1264 // local layout information
1265 docstring const local_layout = getLocalLayout(false);
1266 if (!local_layout.empty()) {
1267 // remove '\n' from the end
1268 docstring const tmplocal = rtrim(local_layout, "\n");
1269 os << "\\begin_local_layout\n"
1270 << to_utf8(tmplocal)
1271 << "\n\\end_local_layout\n";
1273 docstring const forced_local_layout = getLocalLayout(true);
1274 if (!forced_local_layout.empty()) {
1275 // remove '\n' from the end
1276 docstring const tmplocal = rtrim(forced_local_layout, "\n");
1277 os << "\\begin_forced_local_layout\n"
1278 << to_utf8(tmplocal)
1279 << "\n\\end_forced_local_layout\n";
1282 // then the text parameters
1283 if (language != ignore_language)
1284 os << "\\language " << language->lang() << '\n';
1285 os << "\\language_package " << lang_package
1286 << "\n\\inputencoding " << inputenc
1287 << "\n\\fontencoding " << fontenc
1288 << "\n\\font_roman \"" << fonts_roman[0]
1289 << "\" \"" << fonts_roman[1] << '"'
1290 << "\n\\font_sans \"" << fonts_sans[0]
1291 << "\" \"" << fonts_sans[1] << '"'
1292 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1293 << "\" \"" << fonts_typewriter[1] << '"'
1294 << "\n\\font_math \"" << fonts_math[0]
1295 << "\" \"" << fonts_math[1] << '"'
1296 << "\n\\font_default_family " << fonts_default_family
1297 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1298 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1299 << "\n\\font_roman_osf " << convert<string>(fonts_roman_osf)
1300 << "\n\\font_sans_osf " << convert<string>(fonts_sans_osf)
1301 << "\n\\font_typewriter_osf " << convert<string>(fonts_typewriter_osf);
1302 if (!font_roman_opts.empty())
1303 os << "\n\\font_roman_opts \"" << font_roman_opts << "\"";
1304 os << "\n\\font_sf_scale " << fonts_sans_scale[0]
1305 << ' ' << fonts_sans_scale[1];
1306 if (!font_sans_opts.empty())
1307 os << "\n\\font_sans_opts \"" << font_sans_opts << "\"";
1308 os << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1309 << ' ' << fonts_typewriter_scale[1];
1310 if (!font_typewriter_opts.empty())
1311 os << "\n\\font_typewriter_opts \"" << font_typewriter_opts << "\"";
1313 if (!fonts_cjk.empty())
1314 os << "\\font_cjk " << fonts_cjk << '\n';
1315 os << "\\use_microtype " << convert<string>(use_microtype) << '\n';
1316 os << "\\use_dash_ligatures " << convert<string>(use_dash_ligatures) << '\n';
1317 os << "\\graphics " << graphics_driver << '\n';
1318 os << "\\default_output_format " << default_output_format << '\n';
1319 os << "\\output_sync " << output_sync << '\n';
1320 if (!output_sync_macro.empty())
1321 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1322 os << "\\bibtex_command " << bibtex_command << '\n';
1323 os << "\\index_command " << index_command << '\n';
1325 if (!float_placement.empty())
1326 os << "\\float_placement " << float_placement << '\n';
1327 if (!float_alignment.empty())
1328 os << "\\float_alignment " << float_alignment << '\n';
1329 os << "\\paperfontsize " << fontsize << '\n';
1331 spacing().writeFile(os);
1332 pdfoptions().writeFile(os);
1334 os << "\\papersize " << string_papersize[papersize]
1335 << "\n\\use_geometry " << convert<string>(use_geometry);
1336 map<string, string> const & packages = auto_packages();
1337 for (auto const & pack : packages)
1338 os << "\n\\use_package " << pack.first << ' '
1339 << use_package(pack.first);
1341 os << "\n\\cite_engine ";
1343 if (!cite_engine_.empty())
1348 os << "\n\\cite_engine_type " << theCiteEnginesList.getTypeAsString(cite_engine_type_);
1350 if (!biblio_style.empty())
1351 os << "\n\\biblio_style " << biblio_style;
1352 if (!biblio_opts.empty())
1353 os << "\n\\biblio_options " << biblio_opts;
1354 if (!biblatex_bibstyle.empty())
1355 os << "\n\\biblatex_bibstyle " << biblatex_bibstyle;
1356 if (!biblatex_citestyle.empty())
1357 os << "\n\\biblatex_citestyle " << biblatex_citestyle;
1358 if (!multibib.empty())
1359 os << "\n\\multibib " << multibib;
1361 os << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1362 << "\n\\use_indices " << convert<string>(use_indices)
1363 << "\n\\paperorientation " << string_orientation[orientation]
1364 << "\n\\suppress_date " << convert<string>(suppress_date)
1365 << "\n\\justification " << convert<string>(justification)
1366 << "\n\\use_refstyle " << use_refstyle
1367 << "\n\\use_minted " << use_minted
1368 << "\n\\use_lineno " << use_lineno
1371 if (!lineno_opts.empty())
1372 os << "\\lineno_options " << lineno_opts << '\n';
1374 if (isbackgroundcolor == true)
1375 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1376 if (isfontcolor == true)
1377 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1378 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1379 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1380 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1381 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1383 for (auto const & br : branchlist()) {
1384 os << "\\branch " << to_utf8(br.branch())
1385 << "\n\\selected " << br.isSelected()
1386 << "\n\\filename_suffix " << br.hasFileNameSuffix()
1387 << "\n\\color " << lyx::X11hexname(br.color())
1392 for (auto const & id : indiceslist()) {
1393 os << "\\index " << to_utf8(id.index())
1394 << "\n\\shortcut " << to_utf8(id.shortcut())
1395 << "\n\\color " << lyx::X11hexname(id.color())
1400 if (!paperwidth.empty())
1401 os << "\\paperwidth "
1402 << VSpace(paperwidth).asLyXCommand() << '\n';
1403 if (!paperheight.empty())
1404 os << "\\paperheight "
1405 << VSpace(paperheight).asLyXCommand() << '\n';
1406 if (!leftmargin.empty())
1407 os << "\\leftmargin "
1408 << VSpace(leftmargin).asLyXCommand() << '\n';
1409 if (!topmargin.empty())
1410 os << "\\topmargin "
1411 << VSpace(topmargin).asLyXCommand() << '\n';
1412 if (!rightmargin.empty())
1413 os << "\\rightmargin "
1414 << VSpace(rightmargin).asLyXCommand() << '\n';
1415 if (!bottommargin.empty())
1416 os << "\\bottommargin "
1417 << VSpace(bottommargin).asLyXCommand() << '\n';
1418 if (!headheight.empty())
1419 os << "\\headheight "
1420 << VSpace(headheight).asLyXCommand() << '\n';
1421 if (!headsep.empty())
1423 << VSpace(headsep).asLyXCommand() << '\n';
1424 if (!footskip.empty())
1426 << VSpace(footskip).asLyXCommand() << '\n';
1427 if (!columnsep.empty())
1428 os << "\\columnsep "
1429 << VSpace(columnsep).asLyXCommand() << '\n';
1430 os << "\\secnumdepth " << secnumdepth
1431 << "\n\\tocdepth " << tocdepth
1432 << "\n\\paragraph_separation "
1433 << string_paragraph_separation[paragraph_separation];
1434 if (!paragraph_separation)
1435 os << "\n\\paragraph_indentation "
1436 << (getParIndent().empty() ? "default" : getParIndent().asString());
1438 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1439 os << "\n\\is_math_indent " << is_math_indent;
1441 os << "\n\\math_indentation "
1442 << (getMathIndent().empty() ? "default" : getMathIndent().asString());
1443 os << "\n\\math_numbering_side ";
1444 switch(math_numbering_side) {
1454 os << "\n\\quotes_style "
1455 << string_quotes_style[quotes_style]
1456 << "\n\\dynamic_quotes " << dynamic_quotes
1457 << "\n\\papercolumns " << columns
1458 << "\n\\papersides " << sides
1459 << "\n\\paperpagestyle " << pagestyle
1460 << "\n\\tablestyle " << tablestyle << '\n';
1461 if (!listings_params.empty())
1462 os << "\\listings_params \"" <<
1463 InsetListingsParams(listings_params).encodedString() << "\"\n";
1464 for (int i = 0; i < 4; ++i) {
1465 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1466 if (user_defined_bullet(i).getFont() != -1) {
1467 os << "\\bullet " << i << " "
1468 << user_defined_bullet(i).getFont() << " "
1469 << user_defined_bullet(i).getCharacter() << " "
1470 << user_defined_bullet(i).getSize() << "\n";
1474 os << "\\bulletLaTeX " << i << " \""
1475 << lyx::to_ascii(user_defined_bullet(i).getText())
1481 os << "\\tracking_changes "
1482 << (save_transient_properties ? convert<string>(track_changes) : "false")
1485 os << "\\output_changes "
1486 << (save_transient_properties ? convert<string>(output_changes) : "false")
1489 os << "\\change_bars "
1490 << (save_transient_properties ? convert<string>(change_bars) : "false")
1493 os << "\\postpone_fragile_content " << convert<string>(postpone_fragile_content) << '\n';
1495 os << "\\html_math_output " << html_math_output << '\n'
1496 << "\\html_css_as_file " << html_css_as_file << '\n'
1497 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1499 os << "\\docbook_table_output " << docbook_table_output << '\n';
1501 if (html_math_img_scale != 1.0)
1502 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1503 if (!html_latex_start.empty())
1504 os << "\\html_latex_start " << html_latex_start << '\n';
1505 if (!html_latex_end.empty())
1506 os << "\\html_latex_end " << html_latex_end << '\n';
1508 os << pimpl_->authorlist;
1512 void BufferParams::validate(LaTeXFeatures & features) const
1514 features.require(documentClass().required());
1516 if (columns > 1 && language->rightToLeft())
1517 features.require("rtloutputdblcol");
1519 if (output_changes) {
1520 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1521 LaTeXFeatures::isAvailable("xcolor");
1523 switch (features.runparams().flavor) {
1524 case OutputParams::LATEX:
1525 case OutputParams::DVILUATEX:
1527 features.require("ct-xcolor-ulem");
1528 features.require("ulem");
1529 features.require("xcolor");
1531 features.require("ct-none");
1534 case OutputParams::LUATEX:
1535 case OutputParams::PDFLATEX:
1536 case OutputParams::XETEX:
1538 features.require("ct-xcolor-ulem");
1539 features.require("ulem");
1540 features.require("xcolor");
1541 // improves color handling in PDF output
1542 features.require("pdfcolmk");
1544 features.require("ct-none");
1551 features.require("changebar");
1554 // Floats with 'Here definitely' as default setting.
1555 if (float_placement.find('H') != string::npos)
1556 features.require("float");
1558 for (auto const & pm : use_packages) {
1559 if (pm.first == "amsmath") {
1560 // AMS Style is at document level
1561 if (pm.second == package_on ||
1562 features.isProvided("amsmath"))
1563 features.require(pm.first);
1564 } else if (pm.second == package_on)
1565 features.require(pm.first);
1568 // Document-level line spacing
1569 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1570 features.require("setspace");
1572 // the bullet shapes are buffer level not paragraph level
1573 // so they are tested here
1574 for (int i = 0; i < 4; ++i) {
1575 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1577 int const font = user_defined_bullet(i).getFont();
1579 int const c = user_defined_bullet(i).getCharacter();
1585 features.require("latexsym");
1587 } else if (font == 1) {
1588 features.require("amssymb");
1589 } else if (font >= 2 && font <= 5) {
1590 features.require("pifont");
1594 if (pdfoptions().use_hyperref) {
1595 features.require("hyperref");
1596 // due to interferences with babel and hyperref, the color package has to
1597 // be loaded after hyperref when hyperref is used with the colorlinks
1598 // option, see http://www.lyx.org/trac/ticket/5291
1599 if (pdfoptions().colorlinks)
1600 features.require("color");
1602 if (!listings_params.empty()) {
1603 // do not test validity because listings_params is
1604 // supposed to be valid
1606 InsetListingsParams(listings_params).separatedParams(true);
1607 // we can't support all packages, but we should load the color package
1608 if (par.find("\\color", 0) != string::npos)
1609 features.require("color");
1612 // some languages are only available via polyglossia
1613 if (features.hasPolyglossiaExclusiveLanguages())
1614 features.require("polyglossia");
1616 if (useNonTeXFonts && fontsMath() != "auto")
1617 features.require("unicode-math");
1620 features.require("microtype");
1622 if (!language->required().empty())
1623 features.require(language->required());
1627 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1628 FileName const & filepath) const
1630 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1631 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1632 // \RequirePackage to do so, rather than the normal \usepackage
1633 // Do not try to load any other package before the document class, unless you
1634 // have a thorough understanding of the LATEX internals and know exactly what you
1636 if (features.mustProvide("fix-cm"))
1637 os << "\\RequirePackage{fix-cm}\n";
1638 // Likewise for fixltx2e. If other packages conflict with this policy,
1639 // treat it as a package bug (and report it!)
1640 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1641 if (features.mustProvide("fixltx2e"))
1642 os << "\\RequirePackage{fixltx2e}\n";
1644 os << "\\documentclass";
1646 DocumentClass const & tclass = documentClass();
1648 ostringstream clsoptions; // the document class options.
1650 if (tokenPos(tclass.opt_fontsize(),
1651 '|', fontsize) >= 0) {
1652 // only write if existing in list (and not default)
1653 clsoptions << subst(tclass.fontsizeformat(), "$$s", fontsize) << ",";
1656 // paper sizes not supported by the class itself need the
1658 vector<string> classpsizes = getVectorFromString(tclass.opt_pagesize(), "|");
1659 bool class_supported_papersize = papersize == PAPER_DEFAULT
1660 || find(classpsizes.begin(), classpsizes.end(), string_papersize[papersize]) != classpsizes.end();
1662 if ((!use_geometry || features.isProvided("geometry-light"))
1663 && class_supported_papersize && papersize != PAPER_DEFAULT)
1664 clsoptions << subst(tclass.pagesizeformat(), "$$s", string_papersize[papersize]) << ",";
1667 if (sides != tclass.sides()) {
1670 clsoptions << "oneside,";
1673 clsoptions << "twoside,";
1679 if (columns != tclass.columns()) {
1681 clsoptions << "twocolumn,";
1683 clsoptions << "onecolumn,";
1687 && orientation == ORIENTATION_LANDSCAPE)
1688 clsoptions << "landscape,";
1691 clsoptions << "fleqn,";
1693 switch(math_numbering_side) {
1695 clsoptions << "leqno,";
1698 clsoptions << "reqno,";
1699 features.require("amsmath");
1705 // language should be a parameter to \documentclass
1706 if (language->babel() == "hebrew"
1707 && default_language->babel() != "hebrew")
1708 // This seems necessary
1709 features.useLanguage(default_language);
1711 ostringstream language_options;
1712 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1713 bool const use_polyglossia = features.usePolyglossia();
1714 bool const global = lyxrc.language_global_options;
1715 if (features.useBabel() || (use_polyglossia && global)) {
1716 language_options << features.getBabelLanguages();
1717 if (!language->babel().empty()) {
1718 if (!language_options.str().empty())
1719 language_options << ',';
1720 language_options << language->babel();
1722 if (global && !language_options.str().empty())
1723 clsoptions << language_options.str() << ',';
1726 // the predefined options from the layout
1727 if (use_default_options && !tclass.options().empty())
1728 clsoptions << tclass.options() << ',';
1730 // the user-defined options
1731 if (!options.empty()) {
1732 clsoptions << options << ',';
1735 docstring const strOptions = from_utf8(clsoptions.str());
1736 if (!strOptions.empty()) {
1737 // Check if class options contain uncodable glyphs
1738 docstring uncodable_glyphs;
1739 docstring options_encodable;
1740 Encoding const * const enc = features.runparams().encoding;
1742 for (size_t n = 0; n < strOptions.size(); ++n) {
1743 char_type c = strOptions[n];
1744 if (!enc->encodable(c)) {
1745 docstring const glyph(1, c);
1746 LYXERR0("Uncodable character '"
1748 << "' in class options!");
1749 uncodable_glyphs += glyph;
1750 if (features.runparams().dryrun) {
1751 options_encodable += "<" + _("LyX Warning: ")
1752 + _("uncodable character") + " '";
1753 options_encodable += c;
1754 options_encodable += "'>";
1757 options_encodable += c;
1760 options_encodable = strOptions;
1762 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
1763 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
1764 frontend::Alert::warning(
1765 _("Uncodable character in class options"),
1767 _("The class options of your document contain glyphs "
1768 "that are unknown in the current document encoding "
1769 "(namely %1$s).\nThese glyphs are omitted "
1770 " from the output, which may result in "
1771 "incomplete output."
1772 "\n\nPlease select an appropriate "
1773 "document encoding\n"
1774 "(such as utf8) or change the "
1775 "class options accordingly."),
1778 options_encodable = rtrim(options_encodable, ",");
1779 os << '[' << options_encodable << ']';
1782 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1783 // end of \documentclass defs
1785 // The package options (via \PassOptionsToPackage)
1786 os << from_ascii(features.getPackageOptions());
1788 // if we use fontspec or newtxmath, we have to load the AMS packages here
1789 string const ams = features.loadAMSPackages();
1790 bool const ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1");
1791 bool const use_newtxmath =
1792 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1793 ot1, false, false) == "newtxmath";
1794 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1795 os << from_ascii(ams);
1797 if (useNonTeXFonts) {
1798 // Babel (as of 2017/11/03) loads fontspec itself
1799 if (!features.isProvided("fontspec")
1800 && !(features.useBabel() && features.isAvailable("babel-2017/11/03")))
1801 os << "\\usepackage{fontspec}\n";
1802 if (features.mustProvide("unicode-math")
1803 && features.isAvailable("unicode-math"))
1804 os << "\\usepackage{unicode-math}\n";
1807 // load CJK support package before font selection
1808 // (see autotests/export/latex/CJK/micro-sign_utf8-cjk-libertine.lyx)
1809 if (!useNonTeXFonts && encoding().package() != Encoding::none && inputenc != "utf8x"
1810 && (encoding().package() == Encoding::CJK || features.mustProvide("CJK"))) {
1811 if (inputenc == "utf8-cjk" || inputenc == "utf8")
1812 os << "\\usepackage{CJKutf8}\n";
1814 os << "\\usepackage[encapsulated]{CJK}\n";
1817 // font selection must be done before loading fontenc.sty
1818 // but after babel with non-TeX fonts
1819 string const fonts = loadFonts(features);
1820 if (!fonts.empty() && (!features.useBabel() || !useNonTeXFonts))
1821 os << from_utf8(fonts);
1823 if (fonts_default_family != "default")
1824 os << "\\renewcommand{\\familydefault}{\\"
1825 << from_ascii(fonts_default_family) << "}\n";
1827 // set font encoding
1828 // non-TeX fonts use font encoding TU (set by fontspec)
1829 if (!useNonTeXFonts && !features.isProvided("fontenc")
1830 && main_font_encoding() != "default") {
1831 // get main font encodings
1832 vector<string> fontencs = font_encodings();
1833 // get font encodings of secondary languages
1834 // FIXME: some languages (hebrew, ...) assume a standard font encoding as last
1835 // option (for text in other languages).
1836 features.getFontEncodings(fontencs);
1837 if (!fontencs.empty()) {
1838 os << "\\usepackage["
1839 << from_ascii(getStringFromVector(fontencs))
1844 // Load textcomp and pmboxdraw before (lua)inputenc (#11454)
1845 if (features.mustProvide("textcomp"))
1846 os << "\\usepackage{textcomp}\n";
1847 if (features.mustProvide("pmboxdraw"))
1848 os << "\\usepackage{pmboxdraw}\n";
1850 // handle inputenc etc.
1851 // (In documents containing text in Thai language,
1852 // we must load inputenc after babel, see lib/languages).
1853 if (!contains(features.getBabelPostsettings(), from_ascii("thai.ldf")))
1854 writeEncodingPreamble(os, features);
1857 if (!features.runparams().includeall && !included_children_.empty()) {
1858 os << "\\includeonly{";
1860 for (auto incfile : included_children_) {
1861 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1862 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1864 if (!features.runparams().nice)
1866 // \includeonly doesn't want an extension
1867 incfile = changeExtension(incfile, string());
1868 incfile = support::latex_path(incfile);
1869 if (!incfile.empty()) {
1872 os << from_utf8(incfile);
1879 if (!features.isProvided("geometry")
1880 && (use_geometry || !class_supported_papersize)) {
1881 odocstringstream ods;
1882 if (!getGraphicsDriver("geometry").empty())
1883 ods << getGraphicsDriver("geometry");
1884 if (orientation == ORIENTATION_LANDSCAPE)
1885 ods << ",landscape";
1886 switch (papersize) {
1888 if (!paperwidth.empty())
1889 ods << ",paperwidth="
1890 << from_ascii(paperwidth);
1891 if (!paperheight.empty())
1892 ods << ",paperheight="
1893 << from_ascii(paperheight);
1895 case PAPER_USLETTER:
1897 case PAPER_USEXECUTIVE:
1926 ods << "," << from_ascii(string_papersize_geometry[papersize]);
1931 docstring g_options = trim(ods.str(), ",");
1932 os << "\\usepackage";
1933 // geometry-light means that the class works with geometry, but overwrites
1934 // the package options and paper sizes (memoir does this).
1935 // In this case, all options need to go to \geometry
1936 // and the standard paper sizes need to go to the class options.
1937 if (!g_options.empty() && !features.isProvided("geometry-light")) {
1938 os << '[' << g_options << ']';
1941 os << "{geometry}\n";
1942 if (use_geometry || features.isProvided("geometry-light")) {
1943 os << "\\geometry{verbose";
1944 if (!g_options.empty())
1945 // Output general options here with "geometry light".
1946 os << "," << g_options;
1947 // output this only if use_geometry is true
1949 if (!topmargin.empty())
1950 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1951 if (!bottommargin.empty())
1952 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1953 if (!leftmargin.empty())
1954 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1955 if (!rightmargin.empty())
1956 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1957 if (!headheight.empty())
1958 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1959 if (!headsep.empty())
1960 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1961 if (!footskip.empty())
1962 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1963 if (!columnsep.empty())
1964 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1968 } else if (orientation == ORIENTATION_LANDSCAPE
1969 || papersize != PAPER_DEFAULT) {
1970 features.require("papersize");
1973 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1974 if (pagestyle == "fancy")
1975 os << "\\usepackage{fancyhdr}\n";
1976 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1979 // only output when the background color is not default
1980 if (isbackgroundcolor == true) {
1981 // only require color here, the background color will be defined
1982 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1984 features.require("color");
1985 features.require("pagecolor");
1988 // only output when the font color is not default
1989 if (isfontcolor == true) {
1990 // only require color here, the font color will be defined
1991 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1993 features.require("color");
1994 features.require("fontcolor");
1997 // Only if class has a ToC hierarchy
1998 if (tclass.hasTocLevels()) {
1999 if (secnumdepth != tclass.secnumdepth()) {
2000 os << "\\setcounter{secnumdepth}{"
2004 if (tocdepth != tclass.tocdepth()) {
2005 os << "\\setcounter{tocdepth}{"
2011 if (paragraph_separation) {
2012 // when skip separation
2014 switch (getDefSkip().kind()) {
2015 case VSpace::SMALLSKIP:
2016 psopt = "\\smallskipamount";
2018 case VSpace::MEDSKIP:
2019 psopt = "\\medskipamount";
2021 case VSpace::BIGSKIP:
2022 psopt = "\\bigskipamount";
2024 case VSpace::HALFLINE:
2025 // default (no option)
2027 case VSpace::FULLLINE:
2028 psopt = "\\baselineskip";
2030 case VSpace::LENGTH:
2031 psopt = getDefSkip().length().asLatexString();
2036 if (!features.isProvided("parskip")) {
2038 psopt = "[skip=" + psopt + "]";
2039 os << "\\usepackage" + psopt + "{parskip}\n";
2041 os << "\\setlength{\\parskip}{" + psopt + "}\n";
2044 // when separation by indentation
2045 // only output something when a width is given
2046 if (!getParIndent().empty()) {
2047 os << "\\setlength{\\parindent}{"
2048 << from_utf8(getParIndent().asLatexString())
2053 if (is_math_indent) {
2054 // when formula indentation
2055 // only output something when it is not the default
2056 if (!getMathIndent().empty()) {
2057 os << "\\setlength{\\mathindent}{"
2058 << from_utf8(getMathIndent().asString())
2063 // Now insert the LyX specific LaTeX commands...
2064 features.resolveAlternatives();
2065 features.expandMultiples();
2068 if (!output_sync_macro.empty())
2069 os << from_utf8(output_sync_macro) +"\n";
2070 else if (features.runparams().flavor == OutputParams::LATEX)
2071 os << "\\usepackage[active]{srcltx}\n";
2072 else if (features.runparams().flavor == OutputParams::PDFLATEX)
2073 os << "\\synctex=-1\n";
2076 // due to interferences with babel and hyperref, the color package has to
2077 // be loaded (when it is not already loaded) before babel when hyperref
2078 // is used with the colorlinks option, see
2079 // http://www.lyx.org/trac/ticket/5291
2080 // we decided therefore to load color always before babel, see
2081 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
2082 os << from_ascii(features.getColorOptions());
2084 // If we use hyperref, jurabib, japanese or varioref,
2085 // we have to call babel before
2087 && (features.isRequired("jurabib")
2088 || features.isRequired("hyperref")
2089 || features.isRequired("varioref")
2090 || features.isRequired("japanese"))) {
2091 os << features.getBabelPresettings();
2093 os << from_utf8(babelCall(language_options.str(),
2094 !lyxrc.language_global_options)) + '\n';
2095 os << features.getBabelPostsettings();
2098 // The optional packages;
2099 os << from_ascii(features.getPackages());
2101 // Additional Indices
2102 if (features.isRequired("splitidx")) {
2103 for (auto const & idx : indiceslist()) {
2104 os << "\\newindex{";
2105 os << escape(idx.shortcut());
2111 os << from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
2114 // * Hyperref manual: "Make sure it comes last of your loaded
2115 // packages, to give it a fighting chance of not being over-written,
2116 // since its job is to redefine many LaTeX commands."
2117 // * Email from Heiko Oberdiek: "It is usually better to load babel
2118 // before hyperref. Then hyperref has a chance to detect babel.
2119 // * Has to be loaded before the "LyX specific LaTeX commands" to
2120 // avoid errors with algorithm floats.
2121 // use hyperref explicitly if it is required
2122 if (features.isRequired("hyperref")) {
2123 OutputParams tmp_params = features.runparams();
2124 pdfoptions().writeLaTeX(tmp_params, os,
2125 features.isProvided("hyperref"));
2126 // correctly break URLs with hyperref and dvi/ps output
2127 if (features.runparams().hyperref_driver == "dvips"
2128 && features.isAvailable("breakurl"))
2129 os << "\\usepackage{breakurl}\n";
2130 } else if (features.isRequired("nameref"))
2131 // hyperref loads this automatically
2132 os << "\\usepackage{nameref}\n";
2135 os << "\\usepackage";
2136 if (!lineno_opts.empty())
2137 os << "[" << lineno_opts << "]";
2139 os << "\\linenumbers\n";
2142 // bibtopic needs to be loaded after hyperref.
2143 // the dot provides the aux file naming which LyX can detect.
2144 if (features.mustProvide("bibtopic"))
2145 os << "\\usepackage[dot]{bibtopic}\n";
2147 // Will be surrounded by \makeatletter and \makeatother when not empty
2148 otexstringstream atlyxpreamble;
2150 // Some macros LyX will need
2152 TexString tmppreamble = features.getMacros();
2153 if (!tmppreamble.str.empty())
2154 atlyxpreamble << "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2155 "LyX specific LaTeX commands.\n"
2156 << move(tmppreamble)
2159 // the text class specific preamble
2161 docstring tmppreamble = features.getTClassPreamble();
2162 if (!tmppreamble.empty())
2163 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2164 "Textclass specific LaTeX commands.\n"
2168 // suppress date if selected
2169 // use \@ifundefined because we cannot be sure that every document class
2170 // has a \date command
2172 atlyxpreamble << "\\@ifundefined{date}{}{\\date{}}\n";
2174 /* the user-defined preamble */
2175 if (!containsOnly(preamble, " \n\t")) {
2177 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2178 "User specified LaTeX commands.\n";
2180 // Check if the user preamble contains uncodable glyphs
2181 odocstringstream user_preamble;
2182 docstring uncodable_glyphs;
2183 Encoding const * const enc = features.runparams().encoding;
2185 for (size_t n = 0; n < preamble.size(); ++n) {
2186 char_type c = preamble[n];
2187 if (!enc->encodable(c)) {
2188 docstring const glyph(1, c);
2189 LYXERR0("Uncodable character '"
2191 << "' in user preamble!");
2192 uncodable_glyphs += glyph;
2193 if (features.runparams().dryrun) {
2194 user_preamble << "<" << _("LyX Warning: ")
2195 << _("uncodable character") << " '";
2196 user_preamble.put(c);
2197 user_preamble << "'>";
2200 user_preamble.put(c);
2203 user_preamble << preamble;
2205 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2206 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2207 frontend::Alert::warning(
2208 _("Uncodable character in user preamble"),
2210 _("The user preamble of your document contains glyphs "
2211 "that are unknown in the current document encoding "
2212 "(namely %1$s).\nThese glyphs are omitted "
2213 " from the output, which may result in "
2214 "incomplete output."
2215 "\n\nPlease select an appropriate "
2216 "document encoding\n"
2217 "(such as utf8) or change the "
2218 "preamble code accordingly."),
2221 atlyxpreamble << user_preamble.str() << '\n';
2224 // footmisc must be loaded after setspace
2225 // Load it here to avoid clashes with footmisc loaded in the user
2226 // preamble. For that reason we also pass the options via
2227 // \PassOptionsToPackage in getPreamble() and not here.
2228 if (features.mustProvide("footmisc"))
2229 atlyxpreamble << "\\usepackage{footmisc}\n";
2231 // subfig loads internally the LaTeX package "caption". As
2232 // caption is a very popular package, users will load it in
2233 // the preamble. Therefore we must load subfig behind the
2234 // user-defined preamble and check if the caption package was
2235 // loaded or not. For the case that caption is loaded before
2236 // subfig, there is the subfig option "caption=false". This
2237 // option also works when a koma-script class is used and
2238 // koma's own caption commands are used instead of caption. We
2239 // use \PassOptionsToPackage here because the user could have
2240 // already loaded subfig in the preamble.
2241 if (features.mustProvide("subfig"))
2242 atlyxpreamble << "\\@ifundefined{showcaptionsetup}{}{%\n"
2243 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2244 "\\usepackage{subfig}\n";
2246 // Itemize bullet settings need to be last in case the user
2247 // defines their own bullets that use a package included
2248 // in the user-defined preamble -- ARRae
2249 // Actually it has to be done much later than that
2250 // since some packages like frenchb make modifications
2251 // at \begin{document} time -- JMarc
2252 docstring bullets_def;
2253 for (int i = 0; i < 4; ++i) {
2254 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2255 if (bullets_def.empty())
2256 bullets_def += "\\AtBeginDocument{\n";
2257 bullets_def += " \\def\\labelitemi";
2259 // `i' is one less than the item to modify
2266 bullets_def += "ii";
2272 bullets_def += '{' +
2273 user_defined_bullet(i).getText()
2278 if (!bullets_def.empty())
2279 atlyxpreamble << bullets_def << "}\n\n";
2281 if (!atlyxpreamble.empty())
2282 os << "\n\\makeatletter\n"
2283 << atlyxpreamble.release()
2284 << "\\makeatother\n\n";
2286 // We try to load babel late, in case it interferes with other packages.
2287 // Jurabib, hyperref, varioref, bicaption, menukeys and listings (bug 8995)
2288 // have to be called after babel, though.
2289 if (use_babel && !features.isRequired("jurabib")
2290 && !features.isRequired("hyperref")
2291 && !features.isRequired("varioref")
2292 && !features.isRequired("japanese")) {
2293 os << features.getBabelPresettings();
2295 os << from_utf8(babelCall(language_options.str(),
2296 !lyxrc.language_global_options)) + '\n';
2297 os << features.getBabelPostsettings();
2299 // In documents containing text in Thai language,
2300 // we must load inputenc after babel (see lib/languages).
2301 if (contains(features.getBabelPostsettings(), from_ascii("thai.ldf")))
2302 writeEncodingPreamble(os, features);
2304 // font selection must be done after babel with non-TeX fonts
2305 if (!fonts.empty() && features.useBabel() && useNonTeXFonts)
2306 os << from_utf8(fonts);
2308 if (features.isRequired("bicaption"))
2309 os << "\\usepackage{bicaption}\n";
2310 if (!listings_params.empty()
2311 || features.mustProvide("listings")
2312 || features.mustProvide("minted")) {
2314 os << "\\usepackage{minted}\n";
2316 os << "\\usepackage{listings}\n";
2318 string lst_params = listings_params;
2319 // If minted, do not output the language option (bug 11203)
2320 if (use_minted && contains(lst_params, "language=")) {
2321 vector<string> opts =
2322 getVectorFromString(lst_params, ",", false);
2323 for (size_t i = 0; i < opts.size(); ++i) {
2324 if (prefixIs(opts[i], "language="))
2325 opts.erase(opts.begin() + i--);
2327 lst_params = getStringFromVector(opts, ",");
2329 if (!lst_params.empty()) {
2331 os << "\\setminted{";
2334 // do not test validity because listings_params is
2335 // supposed to be valid
2337 InsetListingsParams(lst_params).separatedParams(true);
2338 os << from_utf8(par);
2342 // xunicode only needs to be loaded if tipa is used
2343 // (the rest is obsoleted by the new TU encoding).
2344 // It needs to be loaded at least after amsmath, amssymb,
2345 // esint and the other packages that provide special glyphs
2346 if (features.mustProvide("tipa") && useNonTeXFonts
2347 && !features.isProvided("xunicode")) {
2348 // The `xunicode` package officially only supports XeTeX,
2349 // but also works with LuaTeX. We work around its XeTeX test.
2350 if (features.runparams().flavor != OutputParams::XETEX) {
2351 os << "% Pretend to xunicode that we are XeTeX\n"
2352 << "\\def\\XeTeXpicfile{}\n";
2354 os << "\\usepackage{xunicode}\n";
2357 // covington must be loaded after beamerarticle
2358 if (features.isRequired("covington"))
2359 os << "\\usepackage{covington}\n";
2361 // Polyglossia must be loaded last ...
2362 if (use_polyglossia) {
2364 os << "\\usepackage{polyglossia}\n";
2365 // set the main language
2366 os << "\\setdefaultlanguage";
2367 if (!language->polyglossiaOpts().empty())
2368 os << "[" << from_ascii(language->polyglossiaOpts()) << "]";
2369 os << "{" << from_ascii(language->polyglossia()) << "}\n";
2370 // now setup the other languages
2371 set<string> const polylangs =
2372 features.getPolyglossiaLanguages();
2373 for (auto const & pl : polylangs) {
2374 // We do not output the options here; they are output in
2375 // the language switch commands. This is safer if multiple
2376 // varieties are used.
2377 if (pl == language->polyglossia())
2379 os << "\\setotherlanguage";
2380 os << "{" << from_ascii(pl) << "}\n";
2384 // ... but before biblatex (see #7065)
2385 if ((features.mustProvide("biblatex")
2386 || features.isRequired("biblatex-chicago"))
2387 && !features.isProvided("biblatex-chicago")
2388 && !features.isProvided("biblatex-natbib")
2389 && !features.isProvided("natbib-internal")
2390 && !features.isProvided("natbib")
2391 && !features.isProvided("jurabib")) {
2392 // The biblatex-chicago package has a differing interface
2393 // it uses a wrapper package and loads styles via fixed options
2394 bool const chicago = features.isRequired("biblatex-chicago");
2397 os << "\\usepackage";
2398 if (!biblatex_bibstyle.empty()
2399 && (biblatex_bibstyle == biblatex_citestyle)
2401 opts = "style=" + biblatex_bibstyle;
2403 } else if (!chicago) {
2404 if (!biblatex_bibstyle.empty()) {
2405 opts = "bibstyle=" + biblatex_bibstyle;
2408 if (!biblatex_citestyle.empty()) {
2409 opts += delim + "citestyle=" + biblatex_citestyle;
2413 if (!multibib.empty() && multibib != "child") {
2414 opts += delim + "refsection=" + multibib;
2417 if (bibtexCommand() == "bibtex8"
2418 || prefixIs(bibtexCommand(), "bibtex8 ")) {
2419 opts += delim + "backend=bibtex8";
2421 } else if (bibtexCommand() == "bibtex"
2422 || prefixIs(bibtexCommand(), "bibtex ")) {
2423 opts += delim + "backend=bibtex";
2426 if (!bib_encoding.empty() && encodings.fromLyXName(bib_encoding)) {
2427 opts += delim + "bibencoding="
2428 + encodings.fromLyXName(bib_encoding)->latexName();
2431 if (!biblio_opts.empty())
2432 opts += delim + biblio_opts;
2434 os << "[" << opts << "]";
2436 os << "{biblatex-chicago}\n";
2438 os << "{biblatex}\n";
2442 // Load custom language package here
2443 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2444 if (lang_package == "default")
2445 os << from_utf8(lyxrc.language_custom_package);
2447 os << from_utf8(lang_package);
2451 // Since menukeys uses catoptions, which does some heavy changes on key-value options,
2452 // it is recommended to load menukeys as the last package (even after hyperref)
2453 if (features.isRequired("menukeys"))
2454 os << "\\usepackage{menukeys}\n";
2456 docstring const i18npreamble =
2457 features.getTClassI18nPreamble(use_babel, use_polyglossia,
2459 if (!i18npreamble.empty())
2460 os << i18npreamble + '\n';
2466 void BufferParams::useClassDefaults()
2468 DocumentClass const & tclass = documentClass();
2470 sides = tclass.sides();
2471 columns = tclass.columns();
2472 pagestyle = tclass.pagestyle();
2473 tablestyle = tclass.tablestyle();
2474 use_default_options = true;
2475 // Only if class has a ToC hierarchy
2476 if (tclass.hasTocLevels()) {
2477 secnumdepth = tclass.secnumdepth();
2478 tocdepth = tclass.tocdepth();
2483 bool BufferParams::hasClassDefaults() const
2485 DocumentClass const & tclass = documentClass();
2487 return sides == tclass.sides()
2488 && columns == tclass.columns()
2489 && pagestyle == tclass.pagestyle()
2490 && tablestyle == tclass.tablestyle()
2491 && use_default_options
2492 && secnumdepth == tclass.secnumdepth()
2493 && tocdepth == tclass.tocdepth();
2497 DocumentClass const & BufferParams::documentClass() const
2503 DocumentClassConstPtr BufferParams::documentClassPtr() const
2509 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2511 // evil, but this function is evil
2512 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2513 invalidateConverterCache();
2517 bool BufferParams::setBaseClass(string const & classname, string const & path)
2519 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2520 LayoutFileList & bcl = LayoutFileList::get();
2521 if (!bcl.haveClass(classname)) {
2523 bformat(_("The layout file:\n"
2525 "could not be found. A default textclass with default\n"
2526 "layouts will be used. LyX will not be able to produce\n"
2528 from_utf8(classname));
2529 frontend::Alert::error(_("Document class not found"), s);
2530 bcl.addEmptyClass(classname);
2533 bool const success = bcl[classname].load(path);
2536 bformat(_("Due to some error in it, the layout file:\n"
2538 "could not be loaded. A default textclass with default\n"
2539 "layouts will be used. LyX will not be able to produce\n"
2541 from_utf8(classname));
2542 frontend::Alert::error(_("Could not load class"), s);
2543 bcl.addEmptyClass(classname);
2546 pimpl_->baseClass_ = classname;
2547 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2552 LayoutFile const * BufferParams::baseClass() const
2554 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2555 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2561 LayoutFileIndex const & BufferParams::baseClassID() const
2563 return pimpl_->baseClass_;
2567 void BufferParams::makeDocumentClass(bool const clone)
2572 invalidateConverterCache();
2573 LayoutModuleList mods;
2574 for (auto const & mod : layout_modules_)
2575 mods.push_back(mod);
2577 doc_class_ = getDocumentClass(*baseClass(), mods, cite_engine_, clone);
2579 TextClass::ReturnValues success = TextClass::OK;
2580 if (!forced_local_layout_.empty())
2581 success = doc_class_->read(to_utf8(forced_local_layout_),
2583 if (!local_layout_.empty() &&
2584 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2585 success = doc_class_->read(to_utf8(local_layout_), TextClass::MODULE);
2586 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2587 docstring const msg = _("Error reading internal layout information");
2588 frontend::Alert::warning(_("Read Error"), msg);
2593 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2595 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2599 docstring BufferParams::getLocalLayout(bool forced) const
2602 return from_utf8(doc_class_->forcedLayouts());
2604 return local_layout_;
2608 void BufferParams::setLocalLayout(docstring const & layout, bool forced)
2611 forced_local_layout_ = layout;
2613 local_layout_ = layout;
2617 bool BufferParams::addLayoutModule(string const & modName)
2619 for (auto const & mod : layout_modules_)
2622 layout_modules_.push_back(modName);
2627 string BufferParams::bufferFormat() const
2629 return documentClass().outputFormat();
2633 bool BufferParams::isExportable(string const & format, bool need_viewable) const
2635 FormatList const & formats = exportableFormats(need_viewable);
2636 for (auto const & fmt : formats) {
2637 if (fmt->name() == format)
2644 FormatList const & BufferParams::exportableFormats(bool only_viewable) const
2646 FormatList & cached = only_viewable ?
2647 pimpl_->viewableFormatList : pimpl_->exportableFormatList;
2648 bool & valid = only_viewable ?
2649 pimpl_->isViewCacheValid : pimpl_->isExportCacheValid;
2653 vector<string> const backs = backends();
2654 set<string> excludes;
2655 if (useNonTeXFonts) {
2656 excludes.insert("latex");
2657 excludes.insert("pdflatex");
2658 } else if (inputenc != "ascii" && inputenc != "utf8-plain") {
2659 // XeTeX with TeX fonts requires input encoding ascii (#10600).
2660 excludes.insert("xetex");
2664 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2665 vector<string>::const_iterator it = backs.begin() + 1;
2666 for (; it != backs.end(); ++it) {
2667 FormatList r = theConverters().getReachable(*it, only_viewable,
2669 result.insert(result.end(), r.begin(), r.end());
2671 sort(result.begin(), result.end(), Format::formatSorter);
2678 vector<string> BufferParams::backends() const
2681 string const buffmt = bufferFormat();
2683 // FIXME: Don't hardcode format names here, but use a flag
2684 if (buffmt == "latex") {
2685 if (encoding().package() == Encoding::japanese)
2686 v.push_back("platex");
2688 if (!useNonTeXFonts) {
2689 v.push_back("pdflatex");
2690 v.push_back("latex");
2693 || inputenc == "ascii" || inputenc == "utf8-plain")
2694 v.push_back("xetex");
2695 v.push_back("luatex");
2696 v.push_back("dviluatex");
2699 string rbuffmt = buffmt;
2700 // If we use an OutputFormat in Japanese docs,
2701 // we need special format in order to get the path
2702 // via pLaTeX (#8823)
2703 if (documentClass().hasOutputFormat()
2704 && encoding().package() == Encoding::japanese)
2706 v.push_back(rbuffmt);
2709 v.push_back("xhtml");
2710 v.push_back("docbook5");
2711 v.push_back("text");
2717 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2719 string const dformat = (format.empty() || format == "default") ?
2720 getDefaultOutputFormat() : format;
2721 DefaultFlavorCache::const_iterator it =
2722 default_flavors_.find(dformat);
2724 if (it != default_flavors_.end())
2727 OutputParams::FLAVOR result = OutputParams::LATEX;
2729 // FIXME It'd be better not to hardcode this, but to do
2730 // something with formats.
2731 if (dformat == "xhtml")
2732 result = OutputParams::HTML;
2733 else if (dformat == "text")
2734 result = OutputParams::TEXT;
2735 else if (dformat == "lyx")
2736 result = OutputParams::LYX;
2737 else if (dformat == "pdflatex")
2738 result = OutputParams::PDFLATEX;
2739 else if (dformat == "xetex")
2740 result = OutputParams::XETEX;
2741 else if (dformat == "luatex")
2742 result = OutputParams::LUATEX;
2743 else if (dformat == "dviluatex")
2744 result = OutputParams::DVILUATEX;
2746 // Try to determine flavor of default output format
2747 vector<string> backs = backends();
2748 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2749 // Get shortest path to format
2750 Graph::EdgePath path;
2751 for (auto const & bvar : backs) {
2752 Graph::EdgePath p = theConverters().getPath(bvar, dformat);
2753 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2758 result = theConverters().getFlavor(path);
2761 // cache this flavor
2762 default_flavors_[dformat] = result;
2767 string BufferParams::getDefaultOutputFormat() const
2769 if (!default_output_format.empty()
2770 && default_output_format != "default")
2771 return default_output_format;
2772 if (encoding().package() == Encoding::japanese)
2773 return lyxrc.default_platex_view_format;
2775 return lyxrc.default_otf_view_format;
2776 return lyxrc.default_view_format;
2779 Font const BufferParams::getFont() const
2781 FontInfo f = documentClass().defaultfont();
2782 if (fonts_default_family == "rmdefault")
2783 f.setFamily(ROMAN_FAMILY);
2784 else if (fonts_default_family == "sfdefault")
2785 f.setFamily(SANS_FAMILY);
2786 else if (fonts_default_family == "ttdefault")
2787 f.setFamily(TYPEWRITER_FAMILY);
2788 return Font(f, language);
2792 InsetQuotesParams::QuoteStyle BufferParams::getQuoteStyle(string const & qs) const
2794 return quotesstyletranslator().find(qs);
2798 bool BufferParams::isLatex() const
2800 return documentClass().outputType() == LATEX;
2804 bool BufferParams::isLiterate() const
2806 return documentClass().outputType() == LITERATE;
2810 void BufferParams::readPreamble(Lexer & lex)
2812 if (lex.getString() != "\\begin_preamble")
2813 lyxerr << "Error (BufferParams::readPreamble):"
2814 "consistency check failed." << endl;
2816 preamble = lex.getLongString(from_ascii("\\end_preamble"));
2820 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2822 string const expected = forced ? "\\begin_forced_local_layout" :
2823 "\\begin_local_layout";
2824 if (lex.getString() != expected)
2825 lyxerr << "Error (BufferParams::readLocalLayout):"
2826 "consistency check failed." << endl;
2829 forced_local_layout_ =
2830 lex.getLongString(from_ascii("\\end_forced_local_layout"));
2832 local_layout_ = lex.getLongString(from_ascii("\\end_local_layout"));
2836 bool BufferParams::setLanguage(string const & lang)
2838 Language const *new_language = languages.getLanguage(lang);
2839 if (!new_language) {
2840 // Language lang was not found
2843 language = new_language;
2848 void BufferParams::readLanguage(Lexer & lex)
2850 if (!lex.next()) return;
2852 string const tmptok = lex.getString();
2854 // check if tmptok is part of tex_babel in tex-defs.h
2855 if (!setLanguage(tmptok)) {
2856 // Language tmptok was not found
2857 language = default_language;
2858 lyxerr << "Warning: Setting language `"
2859 << tmptok << "' to `" << language->lang()
2865 void BufferParams::readGraphicsDriver(Lexer & lex)
2870 string const tmptok = lex.getString();
2871 // check if tmptok is part of tex_graphics in tex_defs.h
2874 string const test = tex_graphics[n++];
2876 if (test == tmptok) {
2877 graphics_driver = tmptok;
2882 "Warning: graphics driver `$$Token' not recognized!\n"
2883 " Setting graphics driver to `default'.\n");
2884 graphics_driver = "default";
2891 void BufferParams::readBullets(Lexer & lex)
2896 int const index = lex.getInteger();
2898 int temp_int = lex.getInteger();
2899 user_defined_bullet(index).setFont(temp_int);
2900 temp_bullet(index).setFont(temp_int);
2902 user_defined_bullet(index).setCharacter(temp_int);
2903 temp_bullet(index).setCharacter(temp_int);
2905 user_defined_bullet(index).setSize(temp_int);
2906 temp_bullet(index).setSize(temp_int);
2910 void BufferParams::readBulletsLaTeX(Lexer & lex)
2912 // The bullet class should be able to read this.
2915 int const index = lex.getInteger();
2917 docstring const temp_str = lex.getDocString();
2919 user_defined_bullet(index).setText(temp_str);
2920 temp_bullet(index).setText(temp_str);
2924 void BufferParams::readModules(Lexer & lex)
2926 if (!lex.eatLine()) {
2927 lyxerr << "Error (BufferParams::readModules):"
2928 "Unexpected end of input." << endl;
2932 string mod = lex.getString();
2933 if (mod == "\\end_modules")
2935 addLayoutModule(mod);
2941 void BufferParams::readRemovedModules(Lexer & lex)
2943 if (!lex.eatLine()) {
2944 lyxerr << "Error (BufferParams::readRemovedModules):"
2945 "Unexpected end of input." << endl;
2949 string mod = lex.getString();
2950 if (mod == "\\end_removed_modules")
2952 removed_modules_.push_back(mod);
2955 // now we want to remove any removed modules that were previously
2956 // added. normally, that will be because default modules were added in
2957 // setBaseClass(), which gets called when \textclass is read at the
2958 // start of the read.
2959 for (auto const & rm : removed_modules_) {
2960 LayoutModuleList::iterator const mit = layout_modules_.begin();
2961 LayoutModuleList::iterator const men = layout_modules_.end();
2962 LayoutModuleList::iterator found = find(mit, men, rm);
2965 layout_modules_.erase(found);
2970 void BufferParams::readIncludeonly(Lexer & lex)
2972 if (!lex.eatLine()) {
2973 lyxerr << "Error (BufferParams::readIncludeonly):"
2974 "Unexpected end of input." << endl;
2978 string child = lex.getString();
2979 if (child == "\\end_includeonly")
2981 included_children_.push_back(child);
2987 string BufferParams::paperSizeName(PapersizePurpose purpose, string const & psize) const
2989 PAPER_SIZE ppsize = psize.empty() ? papersize : papersizetranslator().find(psize);
2992 if (documentClass().pagesize() == "default")
2993 // could be anything, so don't guess
2995 return paperSizeName(purpose, documentClass().pagesize());
2996 case PAPER_CUSTOM: {
2997 if (purpose == XDVI && !paperwidth.empty() &&
2998 !paperheight.empty()) {
2999 // heightxwidth<unit>
3000 string first = paperwidth;
3001 string second = paperheight;
3002 if (orientation == ORIENTATION_LANDSCAPE)
3005 return first.erase(first.length() - 2)
3011 // dvips and dvipdfm do not know this
3012 if (purpose == DVIPS || purpose == DVIPDFM)
3016 if (purpose == DVIPS || purpose == DVIPDFM)
3020 if (purpose == DVIPS || purpose == DVIPDFM)
3030 if (purpose == DVIPS || purpose == DVIPDFM)
3034 if (purpose == DVIPS || purpose == DVIPDFM)
3038 if (purpose == DVIPS || purpose == DVIPDFM)
3042 if (purpose == DVIPS || purpose == DVIPDFM)
3046 if (purpose == DVIPS || purpose == DVIPDFM)
3050 // dvipdfm does not know this
3051 if (purpose == DVIPDFM)
3055 if (purpose == DVIPDFM)
3059 if (purpose == DVIPS || purpose == DVIPDFM)
3063 if (purpose == DVIPS || purpose == DVIPDFM)
3067 if (purpose == DVIPS || purpose == DVIPDFM)
3071 if (purpose == DVIPS || purpose == DVIPDFM)
3075 if (purpose == DVIPS || purpose == DVIPDFM)
3079 if (purpose == DVIPS || purpose == DVIPDFM)
3083 if (purpose == DVIPS || purpose == DVIPDFM)
3087 if (purpose == DVIPS || purpose == DVIPDFM)
3091 if (purpose == DVIPS || purpose == DVIPDFM)
3095 if (purpose == DVIPS || purpose == DVIPDFM)
3099 if (purpose == DVIPS || purpose == DVIPDFM)
3103 if (purpose == DVIPS || purpose == DVIPDFM)
3107 if (purpose == DVIPS || purpose == DVIPDFM)
3111 if (purpose == DVIPS || purpose == DVIPDFM)
3115 if (purpose == DVIPS || purpose == DVIPDFM)
3118 case PAPER_USEXECUTIVE:
3119 // dvipdfm does not know this
3120 if (purpose == DVIPDFM)
3125 case PAPER_USLETTER:
3127 if (purpose == XDVI)
3134 string const BufferParams::dvips_options() const
3138 // If the class loads the geometry package, we do not know which
3139 // paper size is used, since we do not set it (bug 7013).
3140 // Therefore we must not specify any argument here.
3141 // dvips gets the correct paper size via DVI specials in this case
3142 // (if the class uses the geometry package correctly).
3143 if (documentClass().provides("geometry"))
3147 && papersize == PAPER_CUSTOM
3148 && !lyxrc.print_paper_dimension_flag.empty()
3149 && !paperwidth.empty()
3150 && !paperheight.empty()) {
3151 // using a custom papersize
3152 result = lyxrc.print_paper_dimension_flag;
3153 result += ' ' + paperwidth;
3154 result += ',' + paperheight;
3156 string const paper_option = paperSizeName(DVIPS);
3157 if (!paper_option.empty() && (paper_option != "letter" ||
3158 orientation != ORIENTATION_LANDSCAPE)) {
3159 // dvips won't accept -t letter -t landscape.
3160 // In all other cases, include the paper size
3162 result = lyxrc.print_paper_flag;
3163 result += ' ' + paper_option;
3166 if (orientation == ORIENTATION_LANDSCAPE &&
3167 papersize != PAPER_CUSTOM)
3168 result += ' ' + lyxrc.print_landscape_flag;
3173 string const BufferParams::main_font_encoding() const
3175 if (font_encodings().empty()) {
3176 if (ascii_lowercase(language->fontenc(*this)) == "none")
3180 return font_encodings().back();
3184 vector<string> const BufferParams::font_encodings() const
3186 string doc_fontenc = (fontenc == "auto") ? string() : fontenc;
3188 vector<string> fontencs;
3190 // "default" means "no explicit font encoding"
3191 if (doc_fontenc != "default") {
3192 if (!doc_fontenc.empty())
3193 // If we have a custom setting, we use only that!
3194 return getVectorFromString(doc_fontenc);
3195 if (!language->fontenc(*this).empty()
3196 && ascii_lowercase(language->fontenc(*this)) != "none") {
3197 vector<string> fencs = getVectorFromString(language->fontenc(*this));
3198 for (auto & fe : fencs) {
3199 if (find(fontencs.begin(), fontencs.end(), fe) == fontencs.end())
3200 fontencs.push_back(fe);
3209 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
3211 // suppress the babel call if there is no BabelName defined
3212 // for the document language in the lib/languages file and if no
3213 // other languages are used (lang_opts is then empty)
3214 if (lang_opts.empty())
3216 // The prefs may require the languages to
3217 // be submitted to babel itself (not the class).
3219 return "\\usepackage[" + lang_opts + "]{babel}";
3220 return "\\usepackage{babel}";
3224 docstring BufferParams::getGraphicsDriver(string const & package) const
3228 if (package == "geometry") {
3229 if (graphics_driver == "dvips"
3230 || graphics_driver == "dvipdfm"
3231 || graphics_driver == "pdftex"
3232 || graphics_driver == "vtex")
3233 result = from_ascii(graphics_driver);
3234 else if (graphics_driver == "dvipdfmx")
3235 result = from_ascii("dvipdfm");
3242 void BufferParams::writeEncodingPreamble(otexstream & os,
3243 LaTeXFeatures & features) const
3245 // With no-TeX fonts we use utf8-plain without encoding package.
3249 if (inputenc == "auto-legacy") {
3250 string const doc_encoding =
3251 language->encoding()->latexName();
3252 Encoding::Package const package =
3253 language->encoding()->package();
3255 // Create list of inputenc options:
3256 set<string> encoding_set;
3257 // luainputenc fails with more than one encoding
3258 if (features.runparams().flavor != OutputParams::LUATEX
3259 && features.runparams().flavor != OutputParams::DVILUATEX)
3260 // list all input encodings used in the document
3261 encoding_set = features.getEncodingSet(doc_encoding);
3263 // The "japanese" babel-language requires the pLaTeX engine
3264 // which conflicts with "inputenc".
3265 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
3266 if ((!encoding_set.empty() || package == Encoding::inputenc)
3267 && !features.isRequired("japanese")
3268 && !features.isProvided("inputenc")) {
3269 os << "\\usepackage[";
3270 set<string>::const_iterator it = encoding_set.begin();
3271 set<string>::const_iterator const end = encoding_set.end();
3273 os << from_ascii(*it);
3276 for (; it != end; ++it)
3277 os << ',' << from_ascii(*it);
3278 if (package == Encoding::inputenc) {
3279 if (!encoding_set.empty())
3281 os << from_ascii(doc_encoding);
3283 if (features.runparams().flavor == OutputParams::LUATEX
3284 || features.runparams().flavor == OutputParams::DVILUATEX)
3285 os << "]{luainputenc}\n";
3287 os << "]{inputenc}\n";
3289 } else if (inputenc != "auto-legacy-plain") {
3290 switch (encoding().package()) {
3291 case Encoding::none:
3293 case Encoding::japanese:
3294 if (encoding().iconvName() != "UTF-8"
3295 && !features.runparams().isFullUnicode())
3296 // don't default to [utf8]{inputenc} with TeXLive >= 18
3297 os << "\\ifdefined\\UseRawInputEncoding\n"
3298 << " \\UseRawInputEncoding\\fi\n";
3300 case Encoding::inputenc:
3301 // do not load inputenc if japanese is used
3302 // or if the class provides inputenc
3303 if (features.isRequired("japanese")
3304 || features.isProvided("inputenc"))
3306 os << "\\usepackage[" << from_ascii(encoding().latexName());
3307 if (features.runparams().flavor == OutputParams::LUATEX
3308 || features.runparams().flavor == OutputParams::DVILUATEX)
3309 os << "]{luainputenc}\n";
3311 os << "]{inputenc}\n";
3315 if (inputenc == "auto-legacy-plain" || features.isRequired("japanese")) {
3316 // don't default to [utf8]{inputenc} with TeXLive >= 18
3317 os << "\\ifdefined\\UseRawInputEncoding\n";
3318 os << " \\UseRawInputEncoding\\fi\n";
3323 string const BufferParams::parseFontName(string const & name) const
3325 string mangled = name;
3326 size_t const idx = mangled.find('[');
3327 if (idx == string::npos || idx == 0)
3330 return mangled.substr(0, idx - 1);
3334 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3336 if (fontsRoman() == "default" && fontsSans() == "default"
3337 && fontsTypewriter() == "default"
3338 && (fontsMath() == "default" || fontsMath() == "auto"))
3344 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3345 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3346 * Mapping=tex-text option assures TeX ligatures (such as "--")
3347 * are resolved. Note that tt does not use these ligatures.
3349 * -- add more GUI options?
3350 * -- add more fonts (fonts for other scripts)
3351 * -- if there's a way to find out if a font really supports
3352 * OldStyle, enable/disable the widget accordingly.
3354 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3355 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3356 // However, until v.2 (2010/07/11) fontspec only knew
3357 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3358 // was introduced for both XeTeX and LuaTeX (LuaTeX
3359 // didn't understand "Mapping=tex-text", while XeTeX
3360 // understood both. With most recent versions, both
3361 // variants are understood by both engines. However,
3362 // we want to provide support for at least TeXLive 2009
3363 // (for XeTeX; LuaTeX is only supported as of v.2)
3364 // As of 2017/11/03, Babel has its own higher-level
3365 // interface on top of fontspec that is to be used.
3366 bool const babelfonts = features.useBabel()
3367 && features.isAvailable("babel-2017/11/03");
3368 string const texmapping =
3369 (features.runparams().flavor == OutputParams::XETEX) ?
3370 "Mapping=tex-text" : "Ligatures=TeX";
3371 if (fontsRoman() != "default") {
3373 os << "\\babelfont{rm}[";
3375 os << "\\setmainfont[";
3376 if (!font_roman_opts.empty())
3377 os << font_roman_opts << ',';
3379 if (fonts_roman_osf)
3380 os << ",Numbers=OldStyle";
3381 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3383 if (fontsSans() != "default") {
3384 string const sans = parseFontName(fontsSans());
3385 if (fontsSansScale() != 100) {
3387 os << "\\babelfont{sf}";
3389 os << "\\setsansfont";
3391 << float(fontsSansScale()) / 100 << ',';
3393 os << "Numbers=OldStyle,";
3394 if (!font_sans_opts.empty())
3395 os << font_sans_opts << ',';
3396 os << texmapping << "]{"
3400 os << "\\babelfont{sf}[";
3402 os << "\\setsansfont[";
3404 os << "Numbers=OldStyle,";
3405 if (!font_sans_opts.empty())
3406 os << font_sans_opts << ',';
3407 os << texmapping << "]{"
3411 if (fontsTypewriter() != "default") {
3412 string const mono = parseFontName(fontsTypewriter());
3413 if (fontsTypewriterScale() != 100) {
3415 os << "\\babelfont{tt}";
3417 os << "\\setmonofont";
3419 << float(fontsTypewriterScale()) / 100;
3420 if (fonts_typewriter_osf)
3421 os << ",Numbers=OldStyle";
3422 if (!font_typewriter_opts.empty())
3423 os << ',' << font_typewriter_opts;
3428 os << "\\babelfont{tt}";
3430 os << "\\setmonofont";
3431 if (!font_typewriter_opts.empty() || fonts_typewriter_osf) {
3433 if (fonts_typewriter_osf)
3434 os << "Numbers=OldStyle";
3435 if (!font_typewriter_opts.empty()) {
3436 if (fonts_typewriter_osf)
3438 os << font_typewriter_opts;
3442 os << '{' << mono << "}\n";
3449 bool const ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1");
3450 bool const dryrun = features.runparams().dryrun;
3451 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3452 bool const nomath = (fontsMath() == "default");
3455 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3456 dryrun, ot1, complete, fonts_expert_sc, fonts_roman_osf,
3457 nomath, font_roman_opts);
3460 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3461 dryrun, ot1, complete, fonts_expert_sc, fonts_sans_osf,
3462 nomath, font_sans_opts, fontsSansScale());
3464 // MONOSPACED/TYPEWRITER
3465 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3466 dryrun, ot1, complete, fonts_expert_sc, fonts_typewriter_osf,
3467 nomath, font_typewriter_opts, fontsTypewriterScale());
3470 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3471 dryrun, ot1, complete, fonts_expert_sc, fonts_roman_osf,
3478 Encoding const & BufferParams::encoding() const
3480 // Main encoding for LaTeX output.
3482 return *(encodings.fromLyXName("utf8-plain"));
3483 if (inputenc == "auto-legacy" || inputenc == "auto-legacy-plain")
3484 return *language->encoding();
3485 if (inputenc == "utf8" && language->lang() == "japanese")
3486 return *(encodings.fromLyXName("utf8-platex"));
3487 Encoding const * const enc = encodings.fromLyXName(inputenc);
3490 LYXERR0("Unknown inputenc value `" << inputenc
3491 << "'. Using `auto' instead.");
3492 return *language->encoding();
3496 string const & BufferParams::defaultBiblioStyle() const
3498 if (!biblio_style.empty())
3499 return biblio_style;
3501 map<string, string> const & bs = documentClass().defaultBiblioStyle();
3502 auto cit = bs.find(theCiteEnginesList.getTypeAsString(citeEngineType()));
3503 if (cit != bs.end())
3506 return empty_string();
3510 bool const & BufferParams::fullAuthorList() const
3512 return documentClass().fullAuthorList();
3516 string BufferParams::getCiteAlias(string const & s) const
3518 vector<string> commands =
3519 documentClass().citeCommands(citeEngineType());
3520 // If it is a real command, don't treat it as an alias
3521 if (find(commands.begin(), commands.end(), s) != commands.end())
3523 map<string,string> aliases = documentClass().citeCommandAliases();
3524 if (aliases.find(s) != aliases.end())
3530 vector<string> BufferParams::citeCommands() const
3532 static CitationStyle const default_style;
3533 vector<string> commands =
3534 documentClass().citeCommands(citeEngineType());
3535 if (commands.empty())
3536 commands.push_back(default_style.name);
3541 vector<CitationStyle> BufferParams::citeStyles() const
3543 static CitationStyle const default_style;
3544 vector<CitationStyle> styles =
3545 documentClass().citeStyles(citeEngineType());
3547 styles.push_back(default_style);
3552 string const BufferParams::bibtexCommand() const
3554 // Return document-specific setting if available
3555 if (bibtex_command != "default")
3556 return bibtex_command;
3558 // If we have "default" in document settings, consult the prefs
3559 // 1. Japanese (uses a specific processor)
3560 if (encoding().package() == Encoding::japanese) {
3561 if (lyxrc.jbibtex_command != "automatic")
3562 // Return the specified program, if "automatic" is not set
3563 return lyxrc.jbibtex_command;
3564 else if (!useBiblatex()) {
3565 // With classic BibTeX, return pbibtex, jbibtex, bibtex
3566 if (lyxrc.jbibtex_alternatives.find("pbibtex") != lyxrc.jbibtex_alternatives.end())
3568 if (lyxrc.jbibtex_alternatives.find("jbibtex") != lyxrc.jbibtex_alternatives.end())
3573 // 2. All other languages
3574 else if (lyxrc.bibtex_command != "automatic")
3575 // Return the specified program, if "automatic" is not set
3576 return lyxrc.bibtex_command;
3578 // 3. Automatic: find the most suitable for the current cite framework
3579 if (useBiblatex()) {
3580 // For Biblatex, we prefer biber (also for Japanese)
3581 // and fall back to bibtex8 and, as last resort, bibtex
3582 if (lyxrc.bibtex_alternatives.find("biber") != lyxrc.bibtex_alternatives.end())
3584 else if (lyxrc.bibtex_alternatives.find("bibtex8") != lyxrc.bibtex_alternatives.end())
3591 bool BufferParams::useBiblatex() const
3593 return theCiteEnginesList[citeEngine()]->getCiteFramework() == "biblatex";
3597 void BufferParams::invalidateConverterCache() const
3599 pimpl_->isExportCacheValid = false;
3600 pimpl_->isViewCacheValid = false;
3604 // We shouldn't need to reset the params here, since anything
3605 // we need will be recopied.
3606 void BufferParams::copyForAdvFR(const BufferParams & bp)
3608 string const & lang = bp.language->lang();
3610 layout_modules_ = bp.layout_modules_;
3611 string const & doc_class = bp.documentClass().name();
3612 setBaseClass(doc_class);
3616 void BufferParams::setBibFileEncoding(string const & file, string const & enc)
3618 bib_encodings[file] = enc;
3622 string const BufferParams::bibFileEncoding(string const & file) const
3624 if (bib_encodings.find(file) == bib_encodings.end())
3626 return bib_encodings.find(file)->second;