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", "letterpaper", "legalpaper", "executivepaper",
83 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
84 "a6paper", "b0paper", "b1paper", "b2paper", "b3paper", "b4paper",
85 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
86 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
91 static char const * const string_orientation[] = {
92 "portrait", "landscape", ""
96 static char const * const tex_graphics[] = {
97 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
98 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
99 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
100 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
110 // Paragraph separation
111 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
114 ParSepTranslator const init_parseptranslator()
116 ParSepTranslator translator
117 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
118 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
123 ParSepTranslator const & parseptranslator()
125 static ParSepTranslator const translator =
126 init_parseptranslator();
132 typedef Translator<string, InsetQuotesParams::QuoteStyle> QuotesStyleTranslator;
135 QuotesStyleTranslator const init_quotesstyletranslator()
137 QuotesStyleTranslator translator
138 (string_quotes_style[0], InsetQuotesParams::EnglishQuotes);
139 translator.addPair(string_quotes_style[1], InsetQuotesParams::SwedishQuotes);
140 translator.addPair(string_quotes_style[2], InsetQuotesParams::GermanQuotes);
141 translator.addPair(string_quotes_style[3], InsetQuotesParams::PolishQuotes);
142 translator.addPair(string_quotes_style[4], InsetQuotesParams::SwissQuotes);
143 translator.addPair(string_quotes_style[5], InsetQuotesParams::DanishQuotes);
144 translator.addPair(string_quotes_style[6], InsetQuotesParams::PlainQuotes);
145 translator.addPair(string_quotes_style[7], InsetQuotesParams::BritishQuotes);
146 translator.addPair(string_quotes_style[8], InsetQuotesParams::SwedishGQuotes);
147 translator.addPair(string_quotes_style[9], InsetQuotesParams::FrenchQuotes);
148 translator.addPair(string_quotes_style[10], InsetQuotesParams::FrenchINQuotes);
149 translator.addPair(string_quotes_style[11], InsetQuotesParams::RussianQuotes);
150 translator.addPair(string_quotes_style[12], InsetQuotesParams::CJKQuotes);
151 translator.addPair(string_quotes_style[13], InsetQuotesParams::CJKAngleQuotes);
156 QuotesStyleTranslator const & quotesstyletranslator()
158 static QuotesStyleTranslator const translator =
159 init_quotesstyletranslator();
165 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
168 static PaperSizeTranslator initPaperSizeTranslator()
170 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
171 translator.addPair(string_papersize[1], PAPER_CUSTOM);
172 translator.addPair(string_papersize[2], PAPER_USLETTER);
173 translator.addPair(string_papersize[3], PAPER_USLEGAL);
174 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
175 translator.addPair(string_papersize[5], PAPER_A0);
176 translator.addPair(string_papersize[6], PAPER_A1);
177 translator.addPair(string_papersize[7], PAPER_A2);
178 translator.addPair(string_papersize[8], PAPER_A3);
179 translator.addPair(string_papersize[9], PAPER_A4);
180 translator.addPair(string_papersize[10], PAPER_A5);
181 translator.addPair(string_papersize[11], PAPER_A6);
182 translator.addPair(string_papersize[12], PAPER_B0);
183 translator.addPair(string_papersize[13], PAPER_B1);
184 translator.addPair(string_papersize[14], PAPER_B2);
185 translator.addPair(string_papersize[15], PAPER_B3);
186 translator.addPair(string_papersize[16], PAPER_B4);
187 translator.addPair(string_papersize[17], PAPER_B5);
188 translator.addPair(string_papersize[18], PAPER_B6);
189 translator.addPair(string_papersize[19], PAPER_C0);
190 translator.addPair(string_papersize[20], PAPER_C1);
191 translator.addPair(string_papersize[21], PAPER_C2);
192 translator.addPair(string_papersize[22], PAPER_C3);
193 translator.addPair(string_papersize[23], PAPER_C4);
194 translator.addPair(string_papersize[24], PAPER_C5);
195 translator.addPair(string_papersize[25], PAPER_C6);
196 translator.addPair(string_papersize[26], PAPER_JISB0);
197 translator.addPair(string_papersize[27], PAPER_JISB1);
198 translator.addPair(string_papersize[28], PAPER_JISB2);
199 translator.addPair(string_papersize[29], PAPER_JISB3);
200 translator.addPair(string_papersize[30], PAPER_JISB4);
201 translator.addPair(string_papersize[31], PAPER_JISB5);
202 translator.addPair(string_papersize[32], PAPER_JISB6);
207 PaperSizeTranslator const & papersizetranslator()
209 static PaperSizeTranslator const translator =
210 initPaperSizeTranslator();
216 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
219 PaperOrientationTranslator const init_paperorientationtranslator()
221 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
222 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
227 PaperOrientationTranslator const & paperorientationtranslator()
229 static PaperOrientationTranslator const translator =
230 init_paperorientationtranslator();
236 typedef Translator<int, PageSides> SidesTranslator;
239 SidesTranslator const init_sidestranslator()
241 SidesTranslator translator(1, OneSide);
242 translator.addPair(2, TwoSides);
247 SidesTranslator const & sidestranslator()
249 static SidesTranslator const translator = init_sidestranslator();
255 typedef Translator<int, BufferParams::Package> PackageTranslator;
258 PackageTranslator const init_packagetranslator()
260 PackageTranslator translator(0, BufferParams::package_off);
261 translator.addPair(1, BufferParams::package_auto);
262 translator.addPair(2, BufferParams::package_on);
267 PackageTranslator const & packagetranslator()
269 static PackageTranslator const translator =
270 init_packagetranslator();
276 typedef Translator<string, Spacing::Space> SpaceTranslator;
279 SpaceTranslator const init_spacetranslator()
281 SpaceTranslator translator("default", Spacing::Default);
282 translator.addPair("single", Spacing::Single);
283 translator.addPair("onehalf", Spacing::Onehalf);
284 translator.addPair("double", Spacing::Double);
285 translator.addPair("other", Spacing::Other);
290 SpaceTranslator const & spacetranslator()
292 static SpaceTranslator const translator = init_spacetranslator();
297 bool inSystemDir(FileName const & document_dir, string & system_dir)
299 // A document is assumed to be in a system LyX directory (not
300 // necessarily the system directory of the running instance)
301 // if both "configure.py" and "chkconfig.ltx" are found in
302 // either document_dir/../ or document_dir/../../.
303 // If true, the system directory path is returned in system_dir
304 // with a trailing path separator.
306 string const msg = "Checking whether document is in a system dir...";
308 string dir = document_dir.absFileName();
310 for (int i = 0; i < 3; ++i) {
311 dir = addPath(dir, "..");
312 if (!fileSearch(dir, "configure.py").empty() &&
313 !fileSearch(dir, "chkconfig.ltx").empty()) {
314 LYXERR(Debug::FILES, msg << " yes");
315 system_dir = addPath(FileName(dir).realPath(), "");
320 LYXERR(Debug::FILES, msg << " no");
321 system_dir = string();
328 class BufferParams::Impl
333 AuthorList authorlist;
334 BranchList branchlist;
335 Bullet temp_bullets[4];
336 Bullet user_defined_bullets[4];
337 IndicesList indiceslist;
341 /** This is the amount of space used for paragraph_separation "skip",
342 * and for detached paragraphs in "indented" documents.
345 PDFOptions pdfoptions;
346 LayoutFileIndex baseClass_;
347 FormatList exportableFormatList;
348 FormatList viewableFormatList;
349 bool isViewCacheValid;
350 bool isExportCacheValid;
354 BufferParams::Impl::Impl()
355 : defskip(VSpace::MEDSKIP), baseClass_(string("")),
356 isViewCacheValid(false), isExportCacheValid(false)
358 // set initial author
360 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
365 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
368 return new BufferParams::Impl(*ptr);
372 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
378 BufferParams::BufferParams()
381 setBaseClass(defaultBaseclass());
382 cite_engine_ = "basic";
383 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
385 paragraph_separation = ParagraphIndentSeparation;
386 is_math_indent = false;
387 math_numbering_side = DEFAULT;
388 quotes_style = InsetQuotesParams::EnglishQuotes;
389 dynamic_quotes = false;
390 fontsize = "default";
393 papersize = PAPER_DEFAULT;
394 orientation = ORIENTATION_PORTRAIT;
395 use_geometry = false;
396 biblio_style = string();
397 use_bibtopic = false;
400 save_transient_properties = true;
401 track_changes = false;
402 output_changes = false;
403 use_default_options = true;
404 maintain_unincluded_children = false;
407 language = default_language;
409 fonts_roman[0] = "default";
410 fonts_roman[1] = "default";
411 fonts_sans[0] = "default";
412 fonts_sans[1] = "default";
413 fonts_typewriter[0] = "default";
414 fonts_typewriter[1] = "default";
415 fonts_math[0] = "auto";
416 fonts_math[1] = "auto";
417 fonts_default_family = "default";
418 useNonTeXFonts = false;
419 use_microtype = false;
420 use_dash_ligatures = true;
421 fonts_expert_sc = false;
422 fonts_roman_osf = false;
423 fonts_sans_osf = false;
424 fonts_typewriter_osf = false;
425 fonts_sans_scale[0] = 100;
426 fonts_sans_scale[1] = 100;
427 fonts_typewriter_scale[0] = 100;
428 fonts_typewriter_scale[1] = 100;
430 lang_package = "default";
431 graphics_driver = "default";
432 default_output_format = "default";
433 bibtex_command = "default";
434 index_command = "default";
437 listings_params = string();
438 pagestyle = "default";
439 tablestyle = "default";
440 suppress_date = false;
441 justification = true;
442 // no color is the default (white)
443 backgroundcolor = lyx::rgbFromHexName("#ffffff");
444 isbackgroundcolor = false;
445 // no color is the default (black)
446 fontcolor = lyx::rgbFromHexName("#000000");
448 // light gray is the default font color for greyed-out notes
449 notefontcolor = lyx::rgbFromHexName("#cccccc");
450 boxbgcolor = lyx::rgbFromHexName("#ff0000");
451 compressed = lyxrc.save_compressed;
452 for (int iter = 0; iter < 4; ++iter) {
453 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
454 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
457 indiceslist().addDefault(B_("Index"));
458 html_be_strict = false;
459 html_math_output = MathML;
460 html_math_img_scale = 1.0;
461 html_css_as_file = false;
462 display_pixel_ratio = 1.0;
464 shell_escape = false;
470 // map current author
471 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
475 docstring BufferParams::B_(string const & l10n) const
477 LASSERT(language, return from_utf8(l10n));
478 return getMessages(language->code()).get(l10n);
482 BufferParams::Package BufferParams::use_package(std::string const & p) const
484 PackageMap::const_iterator it = use_packages.find(p);
485 if (it == use_packages.end())
491 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
497 map<string, string> const & BufferParams::auto_packages()
499 static map<string, string> packages;
500 if (packages.empty()) {
501 // We could have a race condition here that two threads
502 // discover an empty map at the same time and want to fill
503 // it, but that is no problem, since the same contents is
504 // filled in twice then. Having the locker inside the
505 // packages.empty() condition has the advantage that we
506 // don't need the mutex overhead for simple reading.
508 Mutex::Locker locker(&mutex);
509 // adding a package here implies a file format change!
510 packages["amsmath"] =
511 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
512 packages["amssymb"] =
513 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
515 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
517 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
518 packages["mathdots"] =
519 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
520 packages["mathtools"] =
521 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
523 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
524 packages["stackrel"] =
525 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
526 packages["stmaryrd"] =
527 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");
528 packages["undertilde"] =
529 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
535 bool BufferParams::useBibtopic() const
539 return (use_bibtopic || (!multibib.empty() && multibib != "child"));
543 AuthorList & BufferParams::authors()
545 return pimpl_->authorlist;
549 AuthorList const & BufferParams::authors() const
551 return pimpl_->authorlist;
555 void BufferParams::addAuthor(Author a)
557 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
561 BranchList & BufferParams::branchlist()
563 return pimpl_->branchlist;
567 BranchList const & BufferParams::branchlist() const
569 return pimpl_->branchlist;
573 IndicesList & BufferParams::indiceslist()
575 return pimpl_->indiceslist;
579 IndicesList const & BufferParams::indiceslist() const
581 return pimpl_->indiceslist;
585 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
587 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
588 return pimpl_->temp_bullets[index];
592 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
594 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
595 return pimpl_->temp_bullets[index];
599 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
601 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
602 return pimpl_->user_defined_bullets[index];
606 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
608 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
609 return pimpl_->user_defined_bullets[index];
613 Spacing & BufferParams::spacing()
615 return pimpl_->spacing;
619 Spacing const & BufferParams::spacing() const
621 return pimpl_->spacing;
625 PDFOptions & BufferParams::pdfoptions()
627 return pimpl_->pdfoptions;
631 PDFOptions const & BufferParams::pdfoptions() const
633 return pimpl_->pdfoptions;
637 Length const & BufferParams::getMathIndent() const
639 return pimpl_->mathindent;
643 void BufferParams::setMathIndent(Length const & indent)
645 pimpl_->mathindent = indent;
649 Length const & BufferParams::getParIndent() const
651 return pimpl_->parindent;
655 void BufferParams::setParIndent(Length const & indent)
657 pimpl_->parindent = indent;
661 VSpace const & BufferParams::getDefSkip() const
663 return pimpl_->defskip;
667 void BufferParams::setDefSkip(VSpace const & vs)
669 // DEFSKIP will cause an infinite loop
670 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
671 pimpl_->defskip = vs;
675 BufferParams::MathNumber BufferParams::getMathNumber() const
677 if (math_numbering_side != DEFAULT)
678 return math_numbering_side;
679 // FIXME: do not hardcode language here
680 else if (language->lang() == "arabic_arabi"
681 || documentClass().provides("leqno"))
688 string BufferParams::readToken(Lexer & lex, string const & token,
689 FileName const & filepath)
693 if (token == "\\textclass") {
695 string const classname = lex.getString();
696 // if there exists a local layout file, ignore the system one
697 // NOTE: in this case, the textclass (.cls file) is assumed to
700 LayoutFileList & bcl = LayoutFileList::get();
701 if (!filepath.empty()) {
702 // If classname is an absolute path, the document is
703 // using a local layout file which could not be accessed
704 // by a relative path. In this case the path is correct
705 // even if the document was moved to a different
706 // location. However, we will have a problem if the
707 // document was generated on a different platform.
708 bool isabsolute = FileName::isAbsolute(classname);
709 string const classpath = onlyPath(classname);
710 string const path = isabsolute ? classpath
711 : FileName(addPath(filepath.absFileName(),
712 classpath)).realPath();
713 string const oldpath = isabsolute ? string()
714 : FileName(addPath(origin, classpath)).realPath();
715 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
717 // that returns non-empty if a "local" layout file is found.
719 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
720 from_utf8(filepath.absFileName())));
723 setBaseClass(onlyFileName(tcp));
725 setBaseClass(onlyFileName(classname));
726 // We assume that a tex class exists for local or unknown
727 // layouts so this warning, will only be given for system layouts.
728 if (!baseClass()->isTeXClassAvailable()) {
729 docstring const desc =
730 translateIfPossible(from_utf8(baseClass()->description()));
731 docstring const prereqs =
732 from_utf8(baseClass()->prerequisites());
733 docstring const msg =
734 bformat(_("The selected document class\n"
736 "requires external files that are not available.\n"
737 "The document class can still be used, but the\n"
738 "document cannot be compiled until the following\n"
739 "prerequisites are installed:\n"
741 "See section 3.1.2.2 (Class Availability) of the\n"
742 "User's Guide for more information."), desc, prereqs);
743 frontend::Alert::warning(_("Document class not available"),
746 } else if (token == "\\save_transient_properties") {
747 lex >> save_transient_properties;
748 } else if (token == "\\origin") {
750 origin = lex.getString();
751 string const sysdirprefix = "/systemlyxdir/";
752 if (prefixIs(origin, sysdirprefix)) {
754 if (inSystemDir(filepath, docsys))
755 origin.replace(0, sysdirprefix.length() - 1, docsys);
757 origin.replace(0, sysdirprefix.length() - 1,
758 package().system_support().absFileName());
760 } else if (token == "\\begin_preamble") {
762 } else if (token == "\\begin_local_layout") {
763 readLocalLayout(lex, false);
764 } else if (token == "\\begin_forced_local_layout") {
765 readLocalLayout(lex, true);
766 } else if (token == "\\begin_modules") {
768 } else if (token == "\\begin_removed_modules") {
769 readRemovedModules(lex);
770 } else if (token == "\\begin_includeonly") {
771 readIncludeonly(lex);
772 } else if (token == "\\maintain_unincluded_children") {
773 lex >> maintain_unincluded_children;
774 } else if (token == "\\options") {
776 options = lex.getString();
777 } else if (token == "\\use_default_options") {
778 lex >> use_default_options;
779 } else if (token == "\\master") {
781 master = lex.getString();
782 if (!filepath.empty() && FileName::isAbsolute(origin)) {
783 bool const isabs = FileName::isAbsolute(master);
784 FileName const abspath(isabs ? master : origin + master);
785 bool const moved = filepath != FileName(origin);
786 if (moved && abspath.exists()) {
787 docstring const path = isabs
789 : from_utf8(abspath.realPath());
790 docstring const refpath =
791 from_utf8(filepath.absFileName());
792 master = to_utf8(makeRelPath(path, refpath));
795 } else if (token == "\\suppress_date") {
796 lex >> suppress_date;
797 } else if (token == "\\justification") {
798 lex >> justification;
799 } else if (token == "\\language") {
801 } else if (token == "\\language_package") {
803 lang_package = lex.getString();
804 } else if (token == "\\inputencoding") {
806 } else if (token == "\\graphics") {
807 readGraphicsDriver(lex);
808 } else if (token == "\\default_output_format") {
809 lex >> default_output_format;
810 } else if (token == "\\bibtex_command") {
812 bibtex_command = lex.getString();
813 } else if (token == "\\index_command") {
815 index_command = lex.getString();
816 } else if (token == "\\fontencoding") {
818 fontenc = lex.getString();
819 } else if (token == "\\font_roman") {
820 lex >> fonts_roman[0];
821 lex >> fonts_roman[1];
822 } else if (token == "\\font_sans") {
823 lex >> fonts_sans[0];
824 lex >> fonts_sans[1];
825 } else if (token == "\\font_typewriter") {
826 lex >> fonts_typewriter[0];
827 lex >> fonts_typewriter[1];
828 } else if (token == "\\font_math") {
829 lex >> fonts_math[0];
830 lex >> fonts_math[1];
831 } else if (token == "\\font_default_family") {
832 lex >> fonts_default_family;
833 } else if (token == "\\use_non_tex_fonts") {
834 lex >> useNonTeXFonts;
835 } else if (token == "\\font_sc") {
836 lex >> fonts_expert_sc;
837 } else if (token == "\\font_roman_osf") {
838 lex >> fonts_roman_osf;
839 } else if (token == "\\font_sans_osf") {
840 lex >> fonts_sans_osf;
841 } else if (token == "\\font_typewriter_osf") {
842 lex >> fonts_typewriter_osf;
843 } else if (token == "\\font_roman_opts") {
844 lex >> font_roman_opts;
845 } else if (token == "\\font_sf_scale") {
846 lex >> fonts_sans_scale[0];
847 lex >> fonts_sans_scale[1];
848 } else if (token == "\\font_sans_opts") {
849 lex >> font_sans_opts;
850 } else if (token == "\\font_tt_scale") {
851 lex >> fonts_typewriter_scale[0];
852 lex >> fonts_typewriter_scale[1];
853 } else if (token == "\\font_typewriter_opts") {
854 lex >> font_typewriter_opts;
855 } else if (token == "\\font_cjk") {
857 } else if (token == "\\use_microtype") {
858 lex >> use_microtype;
859 } else if (token == "\\use_dash_ligatures") {
860 lex >> use_dash_ligatures;
861 } else if (token == "\\paragraph_separation") {
864 paragraph_separation = parseptranslator().find(parsep);
865 } else if (token == "\\paragraph_indentation") {
867 string parindent = lex.getString();
868 if (parindent == "default")
869 pimpl_->parindent = Length();
871 pimpl_->parindent = Length(parindent);
872 } else if (token == "\\defskip") {
874 string const defskip = lex.getString();
875 pimpl_->defskip = VSpace(defskip);
876 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
878 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
879 } else if (token == "\\is_math_indent") {
880 lex >> is_math_indent;
881 } else if (token == "\\math_indentation") {
883 string mathindent = lex.getString();
884 if (mathindent == "default")
885 pimpl_->mathindent = Length();
887 pimpl_->mathindent = Length(mathindent);
888 } else if (token == "\\math_numbering_side") {
892 math_numbering_side = LEFT;
893 else if (tmp == "right")
894 math_numbering_side = RIGHT;
896 math_numbering_side = DEFAULT;
897 } else if (token == "\\quotes_style") {
900 quotes_style = quotesstyletranslator().find(qstyle);
901 } else if (token == "\\dynamic_quotes") {
902 lex >> dynamic_quotes;
903 } else if (token == "\\papersize") {
906 papersize = papersizetranslator().find(ppsize);
907 } else if (token == "\\use_geometry") {
909 } else if (token == "\\use_package") {
914 use_package(package, packagetranslator().find(use));
915 } else if (token == "\\cite_engine") {
917 cite_engine_ = lex.getString();
918 } else if (token == "\\cite_engine_type") {
921 cite_engine_type_ = theCiteEnginesList.getType(engine_type);
922 } else if (token == "\\biblio_style") {
924 biblio_style = lex.getString();
925 } else if (token == "\\biblio_options") {
927 biblio_opts = trim(lex.getString());
928 } else if (token == "\\biblatex_bibstyle") {
930 biblatex_bibstyle = trim(lex.getString());
931 } else if (token == "\\biblatex_citestyle") {
933 biblatex_citestyle = trim(lex.getString());
934 } else if (token == "\\use_bibtopic") {
936 } else if (token == "\\multibib") {
938 } else if (token == "\\use_indices") {
940 } else if (token == "\\tracking_changes") {
941 lex >> track_changes;
942 } else if (token == "\\output_changes") {
943 lex >> output_changes;
944 } else if (token == "\\branch") {
946 docstring branch = lex.getDocString();
947 branchlist().add(branch);
950 string const tok = lex.getString();
951 if (tok == "\\end_branch")
953 Branch * branch_ptr = branchlist().find(branch);
954 if (tok == "\\selected") {
957 branch_ptr->setSelected(lex.getInteger());
959 if (tok == "\\filename_suffix") {
962 branch_ptr->setFileNameSuffix(lex.getInteger());
964 if (tok == "\\color") {
966 string color = lex.getString();
968 branch_ptr->setColor(color);
969 // Update also the Color table:
971 color = lcolor.getX11Name(Color_background);
973 lcolor.setColor(to_utf8(branch), color);
976 } else if (token == "\\index") {
978 docstring index = lex.getDocString();
980 indiceslist().add(index);
983 string const tok = lex.getString();
984 if (tok == "\\end_index")
986 Index * index_ptr = indiceslist().find(index);
987 if (tok == "\\shortcut") {
989 shortcut = lex.getDocString();
991 index_ptr->setShortcut(shortcut);
993 if (tok == "\\color") {
995 string color = lex.getString();
997 index_ptr->setColor(color);
998 // Update also the Color table:
1000 color = lcolor.getX11Name(Color_background);
1002 if (!shortcut.empty())
1003 lcolor.setColor(to_utf8(shortcut), color);
1006 } else if (token == "\\author") {
1008 istringstream ss(lex.getString());
1012 } else if (token == "\\paperorientation") {
1015 orientation = paperorientationtranslator().find(orient);
1016 } else if (token == "\\backgroundcolor") {
1018 backgroundcolor = lyx::rgbFromHexName(lex.getString());
1019 isbackgroundcolor = true;
1020 } else if (token == "\\fontcolor") {
1022 fontcolor = lyx::rgbFromHexName(lex.getString());
1024 } else if (token == "\\notefontcolor") {
1026 string color = lex.getString();
1027 notefontcolor = lyx::rgbFromHexName(color);
1028 lcolor.setColor("notefontcolor", color);
1029 } else if (token == "\\boxbgcolor") {
1031 string color = lex.getString();
1032 boxbgcolor = lyx::rgbFromHexName(color);
1033 lcolor.setColor("boxbgcolor", color);
1034 } else if (token == "\\paperwidth") {
1036 } else if (token == "\\paperheight") {
1038 } else if (token == "\\leftmargin") {
1040 } else if (token == "\\topmargin") {
1042 } else if (token == "\\rightmargin") {
1044 } else if (token == "\\bottommargin") {
1045 lex >> bottommargin;
1046 } else if (token == "\\headheight") {
1048 } else if (token == "\\headsep") {
1050 } else if (token == "\\footskip") {
1052 } else if (token == "\\columnsep") {
1054 } else if (token == "\\paperfontsize") {
1056 } else if (token == "\\papercolumns") {
1058 } else if (token == "\\listings_params") {
1061 listings_params = InsetListingsParams(par).params();
1062 } else if (token == "\\papersides") {
1065 sides = sidestranslator().find(psides);
1066 } else if (token == "\\paperpagestyle") {
1068 } else if (token == "\\tablestyle") {
1070 } else if (token == "\\bullet") {
1072 } else if (token == "\\bulletLaTeX") {
1073 readBulletsLaTeX(lex);
1074 } else if (token == "\\secnumdepth") {
1076 } else if (token == "\\tocdepth") {
1078 } else if (token == "\\spacing") {
1082 if (nspacing == "other") {
1085 spacing().set(spacetranslator().find(nspacing), tmp_val);
1086 } else if (token == "\\float_placement") {
1087 lex >> float_placement;
1088 } else if (token == "\\float_alignment") {
1089 lex >> float_alignment;
1091 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
1092 string toktmp = pdfoptions().readToken(lex, token);
1093 if (!toktmp.empty()) {
1094 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
1098 } else if (token == "\\html_math_output") {
1101 html_math_output = static_cast<MathOutput>(temp);
1102 } else if (token == "\\html_be_strict") {
1103 lex >> html_be_strict;
1104 } else if (token == "\\html_css_as_file") {
1105 lex >> html_css_as_file;
1106 } else if (token == "\\html_math_img_scale") {
1107 lex >> html_math_img_scale;
1108 } else if (token == "\\html_latex_start") {
1110 html_latex_start = lex.getString();
1111 } else if (token == "\\html_latex_end") {
1113 html_latex_end = lex.getString();
1114 } else if (token == "\\output_sync") {
1116 } else if (token == "\\output_sync_macro") {
1117 lex >> output_sync_macro;
1118 } else if (token == "\\use_refstyle") {
1119 lex >> use_refstyle;
1120 } else if (token == "\\use_minted") {
1122 } else if (token == "\\use_lineno") {
1124 } else if (token == "\\lineno_options") {
1126 lineno_opts = trim(lex.getString());
1128 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1138 // Quote argument if it contains spaces
1139 string quoteIfNeeded(string const & str) {
1140 if (contains(str, ' '))
1141 return "\"" + str + "\"";
1147 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1149 // The top of the file is written by the buffer.
1150 // Prints out the buffer info into the .lyx file given by file
1152 os << "\\save_transient_properties "
1153 << convert<string>(save_transient_properties) << '\n';
1155 // the document directory (must end with a path separator)
1156 // realPath() is used to resolve symlinks, while addPath(..., "")
1157 // ensures a trailing path separator.
1159 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1160 string const sysdir = inSystemDir(FileName(filepath), docsys) ? docsys
1161 : addPath(package().system_support().realPath(), "");
1162 string const relpath =
1163 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1164 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1165 filepath = addPath("/systemlyxdir", relpath);
1166 else if (!save_transient_properties || !lyxrc.save_origin)
1167 filepath = "unavailable";
1168 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1171 os << "\\textclass "
1172 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1173 baseClass()->name()), "layout"))
1176 // then the preamble
1177 if (!preamble.empty()) {
1178 // remove '\n' from the end of preamble
1179 docstring const tmppreamble = rtrim(preamble, "\n");
1180 os << "\\begin_preamble\n"
1181 << to_utf8(tmppreamble)
1182 << "\n\\end_preamble\n";
1186 if (!options.empty()) {
1187 os << "\\options " << options << '\n';
1190 // use the class options defined in the layout?
1191 os << "\\use_default_options "
1192 << convert<string>(use_default_options) << "\n";
1194 // the master document
1195 if (!master.empty()) {
1196 os << "\\master " << master << '\n';
1200 if (!removed_modules_.empty()) {
1201 os << "\\begin_removed_modules" << '\n';
1202 list<string>::const_iterator it = removed_modules_.begin();
1203 list<string>::const_iterator en = removed_modules_.end();
1204 for (; it != en; ++it)
1206 os << "\\end_removed_modules" << '\n';
1210 if (!layout_modules_.empty()) {
1211 os << "\\begin_modules" << '\n';
1212 LayoutModuleList::const_iterator it = layout_modules_.begin();
1213 LayoutModuleList::const_iterator en = layout_modules_.end();
1214 for (; it != en; ++it)
1216 os << "\\end_modules" << '\n';
1220 if (!included_children_.empty()) {
1221 os << "\\begin_includeonly" << '\n';
1222 list<string>::const_iterator it = included_children_.begin();
1223 list<string>::const_iterator en = included_children_.end();
1224 for (; it != en; ++it)
1226 os << "\\end_includeonly" << '\n';
1228 os << "\\maintain_unincluded_children "
1229 << convert<string>(maintain_unincluded_children) << '\n';
1231 // local layout information
1232 docstring const local_layout = getLocalLayout(false);
1233 if (!local_layout.empty()) {
1234 // remove '\n' from the end
1235 docstring const tmplocal = rtrim(local_layout, "\n");
1236 os << "\\begin_local_layout\n"
1237 << to_utf8(tmplocal)
1238 << "\n\\end_local_layout\n";
1240 docstring const forced_local_layout = getLocalLayout(true);
1241 if (!forced_local_layout.empty()) {
1242 // remove '\n' from the end
1243 docstring const tmplocal = rtrim(forced_local_layout, "\n");
1244 os << "\\begin_forced_local_layout\n"
1245 << to_utf8(tmplocal)
1246 << "\n\\end_forced_local_layout\n";
1249 // then the text parameters
1250 if (language != ignore_language)
1251 os << "\\language " << language->lang() << '\n';
1252 os << "\\language_package " << lang_package
1253 << "\n\\inputencoding " << inputenc
1254 << "\n\\fontencoding " << fontenc
1255 << "\n\\font_roman \"" << fonts_roman[0]
1256 << "\" \"" << fonts_roman[1] << '"'
1257 << "\n\\font_sans \"" << fonts_sans[0]
1258 << "\" \"" << fonts_sans[1] << '"'
1259 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1260 << "\" \"" << fonts_typewriter[1] << '"'
1261 << "\n\\font_math \"" << fonts_math[0]
1262 << "\" \"" << fonts_math[1] << '"'
1263 << "\n\\font_default_family " << fonts_default_family
1264 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1265 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1266 << "\n\\font_roman_osf " << convert<string>(fonts_roman_osf)
1267 << "\n\\font_sans_osf " << convert<string>(fonts_sans_osf)
1268 << "\n\\font_typewriter_osf " << convert<string>(fonts_typewriter_osf);
1269 if (!font_roman_opts.empty())
1270 os << "\n\\font_roman_opts \"" << font_roman_opts << "\"";
1271 os << "\n\\font_sf_scale " << fonts_sans_scale[0]
1272 << ' ' << fonts_sans_scale[1];
1273 if (!font_sans_opts.empty())
1274 os << "\n\\font_sans_opts \"" << font_sans_opts << "\"";
1275 os << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1276 << ' ' << fonts_typewriter_scale[1];
1277 if (!font_typewriter_opts.empty())
1278 os << "\n\\font_typewriter_opts \"" << font_typewriter_opts << "\"";
1280 if (!fonts_cjk.empty())
1281 os << "\\font_cjk " << fonts_cjk << '\n';
1282 os << "\\use_microtype " << convert<string>(use_microtype) << '\n';
1283 os << "\\use_dash_ligatures " << convert<string>(use_dash_ligatures) << '\n';
1284 os << "\\graphics " << graphics_driver << '\n';
1285 os << "\\default_output_format " << default_output_format << '\n';
1286 os << "\\output_sync " << output_sync << '\n';
1287 if (!output_sync_macro.empty())
1288 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1289 os << "\\bibtex_command " << bibtex_command << '\n';
1290 os << "\\index_command " << index_command << '\n';
1292 if (!float_placement.empty())
1293 os << "\\float_placement " << float_placement << '\n';
1294 if (!float_alignment.empty())
1295 os << "\\float_alignment " << float_alignment << '\n';
1296 os << "\\paperfontsize " << fontsize << '\n';
1298 spacing().writeFile(os);
1299 pdfoptions().writeFile(os);
1301 os << "\\papersize " << string_papersize[papersize]
1302 << "\n\\use_geometry " << convert<string>(use_geometry);
1303 map<string, string> const & packages = auto_packages();
1304 for (map<string, string>::const_iterator it = packages.begin();
1305 it != packages.end(); ++it)
1306 os << "\n\\use_package " << it->first << ' '
1307 << use_package(it->first);
1309 os << "\n\\cite_engine ";
1311 if (!cite_engine_.empty())
1316 os << "\n\\cite_engine_type " << theCiteEnginesList.getTypeAsString(cite_engine_type_);
1318 if (!biblio_style.empty())
1319 os << "\n\\biblio_style " << biblio_style;
1320 if (!biblio_opts.empty())
1321 os << "\n\\biblio_options " << biblio_opts;
1322 if (!biblatex_bibstyle.empty())
1323 os << "\n\\biblatex_bibstyle " << biblatex_bibstyle;
1324 if (!biblatex_citestyle.empty())
1325 os << "\n\\biblatex_citestyle " << biblatex_citestyle;
1326 if (!multibib.empty())
1327 os << "\n\\multibib " << multibib;
1329 os << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1330 << "\n\\use_indices " << convert<string>(use_indices)
1331 << "\n\\paperorientation " << string_orientation[orientation]
1332 << "\n\\suppress_date " << convert<string>(suppress_date)
1333 << "\n\\justification " << convert<string>(justification)
1334 << "\n\\use_refstyle " << use_refstyle
1335 << "\n\\use_minted " << use_minted
1336 << "\n\\use_lineno " << use_lineno
1339 if (!lineno_opts.empty())
1340 os << "\\lineno_options " << lineno_opts << '\n';
1342 if (isbackgroundcolor == true)
1343 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1344 if (isfontcolor == true)
1345 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1346 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1347 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1348 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1349 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1351 BranchList::const_iterator it = branchlist().begin();
1352 BranchList::const_iterator end = branchlist().end();
1353 for (; it != end; ++it) {
1354 os << "\\branch " << to_utf8(it->branch())
1355 << "\n\\selected " << it->isSelected()
1356 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1357 << "\n\\color " << lyx::X11hexname(it->color())
1362 IndicesList::const_iterator iit = indiceslist().begin();
1363 IndicesList::const_iterator iend = indiceslist().end();
1364 for (; iit != iend; ++iit) {
1365 os << "\\index " << to_utf8(iit->index())
1366 << "\n\\shortcut " << to_utf8(iit->shortcut())
1367 << "\n\\color " << lyx::X11hexname(iit->color())
1372 if (!paperwidth.empty())
1373 os << "\\paperwidth "
1374 << VSpace(paperwidth).asLyXCommand() << '\n';
1375 if (!paperheight.empty())
1376 os << "\\paperheight "
1377 << VSpace(paperheight).asLyXCommand() << '\n';
1378 if (!leftmargin.empty())
1379 os << "\\leftmargin "
1380 << VSpace(leftmargin).asLyXCommand() << '\n';
1381 if (!topmargin.empty())
1382 os << "\\topmargin "
1383 << VSpace(topmargin).asLyXCommand() << '\n';
1384 if (!rightmargin.empty())
1385 os << "\\rightmargin "
1386 << VSpace(rightmargin).asLyXCommand() << '\n';
1387 if (!bottommargin.empty())
1388 os << "\\bottommargin "
1389 << VSpace(bottommargin).asLyXCommand() << '\n';
1390 if (!headheight.empty())
1391 os << "\\headheight "
1392 << VSpace(headheight).asLyXCommand() << '\n';
1393 if (!headsep.empty())
1395 << VSpace(headsep).asLyXCommand() << '\n';
1396 if (!footskip.empty())
1398 << VSpace(footskip).asLyXCommand() << '\n';
1399 if (!columnsep.empty())
1400 os << "\\columnsep "
1401 << VSpace(columnsep).asLyXCommand() << '\n';
1402 os << "\\secnumdepth " << secnumdepth
1403 << "\n\\tocdepth " << tocdepth
1404 << "\n\\paragraph_separation "
1405 << string_paragraph_separation[paragraph_separation];
1406 if (!paragraph_separation)
1407 os << "\n\\paragraph_indentation "
1408 << (getParIndent().empty() ? "default" : getParIndent().asString());
1410 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1411 os << "\n\\is_math_indent " << is_math_indent;
1413 os << "\n\\math_indentation "
1414 << (getMathIndent().empty() ? "default" : getMathIndent().asString());
1415 os << "\n\\math_numbering_side ";
1416 switch(math_numbering_side) {
1426 os << "\n\\quotes_style "
1427 << string_quotes_style[quotes_style]
1428 << "\n\\dynamic_quotes " << dynamic_quotes
1429 << "\n\\papercolumns " << columns
1430 << "\n\\papersides " << sides
1431 << "\n\\paperpagestyle " << pagestyle
1432 << "\n\\tablestyle " << tablestyle << '\n';
1433 if (!listings_params.empty())
1434 os << "\\listings_params \"" <<
1435 InsetListingsParams(listings_params).encodedString() << "\"\n";
1436 for (int i = 0; i < 4; ++i) {
1437 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1438 if (user_defined_bullet(i).getFont() != -1) {
1439 os << "\\bullet " << i << " "
1440 << user_defined_bullet(i).getFont() << " "
1441 << user_defined_bullet(i).getCharacter() << " "
1442 << user_defined_bullet(i).getSize() << "\n";
1446 os << "\\bulletLaTeX " << i << " \""
1447 << lyx::to_ascii(user_defined_bullet(i).getText())
1453 os << "\\tracking_changes "
1454 << (save_transient_properties ? convert<string>(track_changes) : "false")
1457 os << "\\output_changes "
1458 << (save_transient_properties ? convert<string>(output_changes) : "false")
1461 os << "\\html_math_output " << html_math_output << '\n'
1462 << "\\html_css_as_file " << html_css_as_file << '\n'
1463 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1465 if (html_math_img_scale != 1.0)
1466 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1467 if (!html_latex_start.empty())
1468 os << "\\html_latex_start " << html_latex_start << '\n';
1469 if (!html_latex_end.empty())
1470 os << "\\html_latex_end " << html_latex_end << '\n';
1472 os << pimpl_->authorlist;
1476 void BufferParams::validate(LaTeXFeatures & features) const
1478 features.require(documentClass().requires());
1480 if (columns > 1 && language->rightToLeft())
1481 features.require("rtloutputdblcol");
1483 if (output_changes) {
1484 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1485 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1486 LaTeXFeatures::isAvailable("xcolor");
1488 switch (features.runparams().flavor) {
1489 case OutputParams::LATEX:
1490 case OutputParams::DVILUATEX:
1492 features.require("ct-dvipost");
1493 features.require("dvipost");
1494 } else if (xcolorulem) {
1495 features.require("ct-xcolor-ulem");
1496 features.require("ulem");
1497 features.require("xcolor");
1499 features.require("ct-none");
1502 case OutputParams::LUATEX:
1503 case OutputParams::PDFLATEX:
1504 case OutputParams::XETEX:
1506 features.require("ct-xcolor-ulem");
1507 features.require("ulem");
1508 features.require("xcolor");
1509 // improves color handling in PDF output
1510 features.require("pdfcolmk");
1512 features.require("ct-none");
1520 // Floats with 'Here definitely' as default setting.
1521 if (float_placement.find('H') != string::npos)
1522 features.require("float");
1524 for (PackageMap::const_iterator it = use_packages.begin();
1525 it != use_packages.end(); ++it) {
1526 if (it->first == "amsmath") {
1527 // AMS Style is at document level
1528 if (it->second == package_on ||
1529 features.isProvided("amsmath"))
1530 features.require(it->first);
1531 } else if (it->second == package_on)
1532 features.require(it->first);
1535 // Document-level line spacing
1536 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1537 features.require("setspace");
1539 // the bullet shapes are buffer level not paragraph level
1540 // so they are tested here
1541 for (int i = 0; i < 4; ++i) {
1542 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1544 int const font = user_defined_bullet(i).getFont();
1546 int const c = user_defined_bullet(i).getCharacter();
1552 features.require("latexsym");
1554 } else if (font == 1) {
1555 features.require("amssymb");
1556 } else if (font >= 2 && font <= 5) {
1557 features.require("pifont");
1561 if (pdfoptions().use_hyperref) {
1562 features.require("hyperref");
1563 // due to interferences with babel and hyperref, the color package has to
1564 // be loaded after hyperref when hyperref is used with the colorlinks
1565 // option, see http://www.lyx.org/trac/ticket/5291
1566 if (pdfoptions().colorlinks)
1567 features.require("color");
1569 if (!listings_params.empty()) {
1570 // do not test validity because listings_params is
1571 // supposed to be valid
1573 InsetListingsParams(listings_params).separatedParams(true);
1574 // we can't support all packages, but we should load the color package
1575 if (par.find("\\color", 0) != string::npos)
1576 features.require("color");
1579 // some languages are only available via polyglossia
1580 if (features.hasPolyglossiaExclusiveLanguages())
1581 features.require("polyglossia");
1583 if (useNonTeXFonts && fontsMath() != "auto")
1584 features.require("unicode-math");
1587 features.require("microtype");
1589 if (!language->requires().empty())
1590 features.require(language->requires());
1594 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1595 FileName const & filepath) const
1597 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1598 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1599 // \RequirePackage to do so, rather than the normal \usepackage
1600 // Do not try to load any other package before the document class, unless you
1601 // have a thorough understanding of the LATEX internals and know exactly what you
1603 if (features.mustProvide("fix-cm"))
1604 os << "\\RequirePackage{fix-cm}\n";
1605 // Likewise for fixltx2e. If other packages conflict with this policy,
1606 // treat it as a package bug (and report it!)
1607 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1608 if (features.mustProvide("fixltx2e"))
1609 os << "\\RequirePackage{fixltx2e}\n";
1611 os << "\\documentclass";
1613 DocumentClass const & tclass = documentClass();
1615 ostringstream clsoptions; // the document class options.
1617 if (tokenPos(tclass.opt_fontsize(),
1618 '|', fontsize) >= 0) {
1619 // only write if existing in list (and not default)
1620 clsoptions << subst(tclass.fontsizeformat(), "$$s", fontsize) << ",";
1623 // paper sizes not supported by the class itself need the
1625 vector<string> classpsizes = getVectorFromString(tclass.opt_pagesize(), "|");
1626 bool class_supported_papersize = papersize == PAPER_DEFAULT
1627 || find(classpsizes.begin(), classpsizes.end(), string_papersize[papersize]) != classpsizes.end();
1629 if ((!use_geometry || features.isProvided("geometry-light"))
1630 && class_supported_papersize)
1631 clsoptions << string_papersize[papersize] << ",";
1634 if (sides != tclass.sides()) {
1637 clsoptions << "oneside,";
1640 clsoptions << "twoside,";
1646 if (columns != tclass.columns()) {
1648 clsoptions << "twocolumn,";
1650 clsoptions << "onecolumn,";
1654 && orientation == ORIENTATION_LANDSCAPE)
1655 clsoptions << "landscape,";
1658 clsoptions << "fleqn,";
1660 switch(math_numbering_side) {
1662 clsoptions << "leqno,";
1665 clsoptions << "reqno,";
1666 features.require("amsmath");
1672 // language should be a parameter to \documentclass
1673 if (language->babel() == "hebrew"
1674 && default_language->babel() != "hebrew")
1675 // This seems necessary
1676 features.useLanguage(default_language);
1678 ostringstream language_options;
1679 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1680 bool const use_polyglossia = features.usePolyglossia();
1681 bool const global = lyxrc.language_global_options;
1682 if (features.useBabel() || (use_polyglossia && global)) {
1683 language_options << features.getBabelLanguages();
1684 if (!language->babel().empty()) {
1685 if (!language_options.str().empty())
1686 language_options << ',';
1687 language_options << language->babel();
1689 if (global && !language_options.str().empty())
1690 clsoptions << language_options.str() << ',';
1693 // the predefined options from the layout
1694 if (use_default_options && !tclass.options().empty())
1695 clsoptions << tclass.options() << ',';
1697 // the user-defined options
1698 if (!options.empty()) {
1699 clsoptions << options << ',';
1702 string strOptions(clsoptions.str());
1703 if (!strOptions.empty()) {
1704 strOptions = rtrim(strOptions, ",");
1706 os << '[' << from_utf8(strOptions) << ']';
1709 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1710 // end of \documentclass defs
1712 // if we use fontspec or newtxmath, we have to load the AMS packages here
1713 string const ams = features.loadAMSPackages();
1714 bool const ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1");
1715 bool const use_newtxmath =
1716 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1717 ot1, false, false) == "newtxmath";
1718 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1719 os << from_ascii(ams);
1721 if (useNonTeXFonts) {
1722 // Babel (as of 2017/11/03) loads fontspec itself
1723 if (!features.isProvided("fontspec")
1724 && !(features.useBabel() && features.isAvailable("babel-2017/11/03")))
1725 os << "\\usepackage{fontspec}\n";
1726 if (features.mustProvide("unicode-math")
1727 && features.isAvailable("unicode-math"))
1728 os << "\\usepackage{unicode-math}\n";
1731 // load CJK support package before font selection
1732 // (see autotests/export/latex/CJK/micro-sign_utf8-cjk-libertine.lyx)
1733 if (!useNonTeXFonts && encoding().package() != Encoding::none && inputenc != "utf8x"
1734 && (encoding().package() == Encoding::CJK || features.mustProvide("CJK"))) {
1735 if (inputenc == "utf8-cjk" || inputenc == "utf8")
1736 os << "\\usepackage{CJKutf8}\n";
1738 os << "\\usepackage[encapsulated]{CJK}\n";
1741 // font selection must be done before loading fontenc.sty
1742 // but after babel with non-TeX fonts
1743 string const fonts = loadFonts(features);
1744 if (!fonts.empty() && (!features.useBabel() || !useNonTeXFonts))
1745 os << from_utf8(fonts);
1747 if (fonts_default_family != "default")
1748 os << "\\renewcommand{\\familydefault}{\\"
1749 << from_ascii(fonts_default_family) << "}\n";
1751 // set font encoding
1752 // non-TeX fonts use font encoding TU (set by fontspec)
1753 if (!useNonTeXFonts && !features.isProvided("fontenc")
1754 && main_font_encoding() != "default") {
1755 // get main font encodings
1756 vector<string> fontencs = font_encodings();
1757 // get font encodings of secondary languages
1758 // FIXME: some languages (hebrew, ...) assume a standard font encoding as last
1759 // option (for text in other languages).
1760 features.getFontEncodings(fontencs);
1761 if (!fontencs.empty()) {
1762 os << "\\usepackage["
1763 << from_ascii(getStringFromVector(fontencs))
1768 // Load textcomp and pmboxdraw before (lua)inputenc (#11454)
1769 if (features.mustProvide("textcomp"))
1770 os << "\\usepackage{textcomp}\n";
1771 if (features.mustProvide("pmboxdraw"))
1772 os << "\\usepackage{pmboxdraw}\n";
1774 // handle inputenc etc.
1775 // (In documents containing text in Thai language,
1776 // we must load inputenc after babel, see lib/languages).
1777 if (!contains(features.getBabelPostsettings(), from_ascii("thai.ldf")))
1778 writeEncodingPreamble(os, features);
1781 if (!features.runparams().includeall && !included_children_.empty()) {
1782 os << "\\includeonly{";
1783 list<string>::const_iterator it = included_children_.begin();
1784 list<string>::const_iterator en = included_children_.end();
1786 for (; it != en; ++it) {
1787 string incfile = *it;
1788 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1789 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1791 if (!features.runparams().nice)
1793 // \includeonly doesn't want an extension
1794 incfile = changeExtension(incfile, string());
1795 incfile = support::latex_path(incfile);
1796 if (!incfile.empty()) {
1799 os << from_utf8(incfile);
1806 if (use_geometry || !class_supported_papersize) {
1807 odocstringstream ods;
1808 if (!getGraphicsDriver("geometry").empty())
1809 ods << getGraphicsDriver("geometry");
1810 if (orientation == ORIENTATION_LANDSCAPE)
1811 ods << ",landscape";
1812 switch (papersize) {
1814 if (!paperwidth.empty())
1815 ods << ",paperwidth="
1816 << from_ascii(paperwidth);
1817 if (!paperheight.empty())
1818 ods << ",paperheight="
1819 << from_ascii(paperheight);
1821 case PAPER_USLETTER:
1823 case PAPER_USEXECUTIVE:
1852 ods << "," << from_ascii(string_papersize[papersize]);
1857 docstring g_options = trim(ods.str(), ",");
1858 // geometry-light means that the class works with geometry, but overwrites
1859 // the package options and paper sizes (memoir does this).
1860 // In this case, all options need to go to \geometry
1861 // and the standard paper sizes need to go to the class options.
1862 if (!features.isProvided("geometry")) {
1863 os << "\\usepackage";
1864 if (!g_options.empty() && !features.isProvided("geometry-light")) {
1865 os << '[' << g_options << ']';
1868 os << "{geometry}\n";
1870 if (use_geometry || features.isProvided("geometry")
1871 || features.isProvided("geometry-light")) {
1872 os << "\\geometry{verbose";
1873 if (!g_options.empty())
1874 // Output general options here with "geometry light".
1875 os << "," << g_options;
1876 // output this only if use_geometry is true
1878 if (!topmargin.empty())
1879 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1880 if (!bottommargin.empty())
1881 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1882 if (!leftmargin.empty())
1883 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1884 if (!rightmargin.empty())
1885 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1886 if (!headheight.empty())
1887 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1888 if (!headsep.empty())
1889 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1890 if (!footskip.empty())
1891 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1892 if (!columnsep.empty())
1893 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1897 } else if (orientation == ORIENTATION_LANDSCAPE
1898 || papersize != PAPER_DEFAULT) {
1899 features.require("papersize");
1902 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1903 if (pagestyle == "fancy")
1904 os << "\\usepackage{fancyhdr}\n";
1905 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1908 // only output when the background color is not default
1909 if (isbackgroundcolor == true) {
1910 // only require color here, the background color will be defined
1911 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1913 features.require("color");
1914 features.require("pagecolor");
1917 // only output when the font color is not default
1918 if (isfontcolor == true) {
1919 // only require color here, the font color will be defined
1920 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1922 features.require("color");
1923 features.require("fontcolor");
1926 // Only if class has a ToC hierarchy
1927 if (tclass.hasTocLevels()) {
1928 if (secnumdepth != tclass.secnumdepth()) {
1929 os << "\\setcounter{secnumdepth}{"
1933 if (tocdepth != tclass.tocdepth()) {
1934 os << "\\setcounter{tocdepth}{"
1940 if (paragraph_separation) {
1941 // when skip separation
1942 switch (getDefSkip().kind()) {
1943 case VSpace::SMALLSKIP:
1944 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1946 case VSpace::MEDSKIP:
1947 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1949 case VSpace::BIGSKIP:
1950 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1952 case VSpace::LENGTH:
1953 os << "\\setlength{\\parskip}{"
1954 << from_utf8(getDefSkip().length().asLatexString())
1957 default: // should never happen // Then delete it.
1958 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1961 os << "\\setlength{\\parindent}{0pt}\n";
1963 // when separation by indentation
1964 // only output something when a width is given
1965 if (!getParIndent().empty()) {
1966 os << "\\setlength{\\parindent}{"
1967 << from_utf8(getParIndent().asLatexString())
1972 if (is_math_indent) {
1973 // when formula indentation
1974 // only output something when it is not the default
1975 if (!getMathIndent().empty()) {
1976 os << "\\setlength{\\mathindent}{"
1977 << from_utf8(getMathIndent().asString())
1982 // Now insert the LyX specific LaTeX commands...
1983 features.resolveAlternatives();
1984 features.expandMultiples();
1987 if (!output_sync_macro.empty())
1988 os << from_utf8(output_sync_macro) +"\n";
1989 else if (features.runparams().flavor == OutputParams::LATEX)
1990 os << "\\usepackage[active]{srcltx}\n";
1991 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1992 os << "\\synctex=-1\n";
1995 // The package options (via \PassOptionsToPackage)
1996 os << from_ascii(features.getPackageOptions());
1998 // due to interferences with babel and hyperref, the color package has to
1999 // be loaded (when it is not already loaded) before babel when hyperref
2000 // is used with the colorlinks option, see
2001 // http://www.lyx.org/trac/ticket/5291
2002 // we decided therefore to load color always before babel, see
2003 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
2004 os << from_ascii(features.getColorOptions());
2006 // If we use hyperref, jurabib, japanese or varioref,
2007 // we have to call babel before
2009 && (features.isRequired("jurabib")
2010 || features.isRequired("hyperref")
2011 || features.isRequired("varioref")
2012 || features.isRequired("japanese"))) {
2013 os << features.getBabelPresettings();
2015 os << from_utf8(babelCall(language_options.str(),
2016 !lyxrc.language_global_options)) + '\n';
2017 os << features.getBabelPostsettings();
2020 // The optional packages;
2021 os << from_ascii(features.getPackages());
2023 // Additional Indices
2024 if (features.isRequired("splitidx")) {
2025 IndicesList::const_iterator iit = indiceslist().begin();
2026 IndicesList::const_iterator iend = indiceslist().end();
2027 for (; iit != iend; ++iit) {
2028 os << "\\newindex{";
2029 os << escape(iit->shortcut());
2035 os << from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
2038 // * Hyperref manual: "Make sure it comes last of your loaded
2039 // packages, to give it a fighting chance of not being over-written,
2040 // since its job is to redefine many LaTeX commands."
2041 // * Email from Heiko Oberdiek: "It is usually better to load babel
2042 // before hyperref. Then hyperref has a chance to detect babel.
2043 // * Has to be loaded before the "LyX specific LaTeX commands" to
2044 // avoid errors with algorithm floats.
2045 // use hyperref explicitly if it is required
2046 if (features.isRequired("hyperref")) {
2047 OutputParams tmp_params = features.runparams();
2048 pdfoptions().writeLaTeX(tmp_params, os,
2049 features.isProvided("hyperref"));
2050 // correctly break URLs with hyperref and dvi/ps output
2051 if (features.runparams().hyperref_driver == "dvips"
2052 && features.isAvailable("breakurl"))
2053 os << "\\usepackage{breakurl}\n";
2054 } else if (features.isRequired("nameref"))
2055 // hyperref loads this automatically
2056 os << "\\usepackage{nameref}\n";
2059 os << "\\usepackage";
2060 if (!lineno_opts.empty())
2061 os << "[" << lineno_opts << "]";
2063 os << "\\linenumbers\n";
2066 // bibtopic needs to be loaded after hyperref.
2067 // the dot provides the aux file naming which LyX can detect.
2068 if (features.mustProvide("bibtopic"))
2069 os << "\\usepackage[dot]{bibtopic}\n";
2071 // Will be surrounded by \makeatletter and \makeatother when not empty
2072 otexstringstream atlyxpreamble;
2074 // Some macros LyX will need
2076 TexString tmppreamble = features.getMacros();
2077 if (!tmppreamble.str.empty())
2078 atlyxpreamble << "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2079 "LyX specific LaTeX commands.\n"
2080 << move(tmppreamble)
2083 // the text class specific preamble
2085 docstring tmppreamble = features.getTClassPreamble();
2086 if (!tmppreamble.empty())
2087 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2088 "Textclass specific LaTeX commands.\n"
2092 // suppress date if selected
2093 // use \@ifundefined because we cannot be sure that every document class
2094 // has a \date command
2096 atlyxpreamble << "\\@ifundefined{date}{}{\\date{}}\n";
2098 /* the user-defined preamble */
2099 if (!containsOnly(preamble, " \n\t")) {
2101 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2102 "User specified LaTeX commands.\n";
2104 // Check if the user preamble contains uncodable glyphs
2105 odocstringstream user_preamble;
2106 docstring uncodable_glyphs;
2107 Encoding const * const enc = features.runparams().encoding;
2109 for (size_t n = 0; n < preamble.size(); ++n) {
2110 char_type c = preamble[n];
2111 if (!enc->encodable(c)) {
2112 docstring const glyph(1, c);
2113 LYXERR0("Uncodable character '"
2115 << "' in user preamble!");
2116 uncodable_glyphs += glyph;
2117 if (features.runparams().dryrun) {
2118 user_preamble << "<" << _("LyX Warning: ")
2119 << _("uncodable character") << " '";
2120 user_preamble.put(c);
2121 user_preamble << "'>";
2124 user_preamble.put(c);
2127 user_preamble << preamble;
2129 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2130 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2131 frontend::Alert::warning(
2132 _("Uncodable character in user preamble"),
2134 _("The user preamble of your document contains glyphs "
2135 "that are unknown in the current document encoding "
2136 "(namely %1$s).\nThese glyphs are omitted "
2137 " from the output, which may result in "
2138 "incomplete output."
2139 "\n\nPlease select an appropriate "
2140 "document encoding\n"
2141 "(such as utf8) or change the "
2142 "preamble code accordingly."),
2145 atlyxpreamble << user_preamble.str() << '\n';
2148 // footmisc must be loaded after setspace
2149 // Load it here to avoid clashes with footmisc loaded in the user
2150 // preamble. For that reason we also pass the options via
2151 // \PassOptionsToPackage in getPreamble() and not here.
2152 if (features.mustProvide("footmisc"))
2153 atlyxpreamble << "\\usepackage{footmisc}\n";
2155 // subfig loads internally the LaTeX package "caption". As
2156 // caption is a very popular package, users will load it in
2157 // the preamble. Therefore we must load subfig behind the
2158 // user-defined preamble and check if the caption package was
2159 // loaded or not. For the case that caption is loaded before
2160 // subfig, there is the subfig option "caption=false". This
2161 // option also works when a koma-script class is used and
2162 // koma's own caption commands are used instead of caption. We
2163 // use \PassOptionsToPackage here because the user could have
2164 // already loaded subfig in the preamble.
2165 if (features.mustProvide("subfig"))
2166 atlyxpreamble << "\\@ifundefined{showcaptionsetup}{}{%\n"
2167 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2168 "\\usepackage{subfig}\n";
2170 // Itemize bullet settings need to be last in case the user
2171 // defines their own bullets that use a package included
2172 // in the user-defined preamble -- ARRae
2173 // Actually it has to be done much later than that
2174 // since some packages like frenchb make modifications
2175 // at \begin{document} time -- JMarc
2176 docstring bullets_def;
2177 for (int i = 0; i < 4; ++i) {
2178 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2179 if (bullets_def.empty())
2180 bullets_def += "\\AtBeginDocument{\n";
2181 bullets_def += " \\def\\labelitemi";
2183 // `i' is one less than the item to modify
2190 bullets_def += "ii";
2196 bullets_def += '{' +
2197 user_defined_bullet(i).getText()
2202 if (!bullets_def.empty())
2203 atlyxpreamble << bullets_def << "}\n\n";
2205 if (!atlyxpreamble.empty())
2206 os << "\n\\makeatletter\n"
2207 << atlyxpreamble.release()
2208 << "\\makeatother\n\n";
2210 // We try to load babel late, in case it interferes with other packages.
2211 // Jurabib, hyperref, varioref, bicaption, menukeys and listings (bug 8995)
2212 // have to be called after babel, though.
2213 if (use_babel && !features.isRequired("jurabib")
2214 && !features.isRequired("hyperref")
2215 && !features.isRequired("varioref")
2216 && !features.isRequired("japanese")) {
2217 os << features.getBabelPresettings();
2219 os << from_utf8(babelCall(language_options.str(),
2220 !lyxrc.language_global_options)) + '\n';
2221 os << features.getBabelPostsettings();
2223 // In documents containing text in Thai language,
2224 // we must load inputenc after babel (see lib/languages).
2225 if (contains(features.getBabelPostsettings(), from_ascii("thai.ldf")))
2226 writeEncodingPreamble(os, features);
2228 // font selection must be done after babel with non-TeX fonts
2229 if (!fonts.empty() && features.useBabel() && useNonTeXFonts)
2230 os << from_utf8(fonts);
2232 if (features.isRequired("bicaption"))
2233 os << "\\usepackage{bicaption}\n";
2234 if (!listings_params.empty()
2235 || features.mustProvide("listings")
2236 || features.mustProvide("minted")) {
2238 os << "\\usepackage{minted}\n";
2240 os << "\\usepackage{listings}\n";
2242 string lst_params = listings_params;
2243 // If minted, do not output the language option (bug 11203)
2244 if (use_minted && contains(lst_params, "language=")) {
2245 vector<string> opts =
2246 getVectorFromString(lst_params, ",", false);
2247 for (size_t i = 0; i < opts.size(); ++i) {
2248 if (prefixIs(opts[i], "language="))
2249 opts.erase(opts.begin() + i--);
2251 lst_params = getStringFromVector(opts, ",");
2253 if (!lst_params.empty()) {
2255 os << "\\setminted{";
2258 // do not test validity because listings_params is
2259 // supposed to be valid
2261 InsetListingsParams(lst_params).separatedParams(true);
2262 os << from_utf8(par);
2266 // xunicode only needs to be loaded if tipa is used
2267 // (the rest is obsoleted by the new TU encoding).
2268 // It needs to be loaded at least after amsmath, amssymb,
2269 // esint and the other packages that provide special glyphs
2270 if (features.mustProvide("tipa") && useNonTeXFonts
2271 && !features.isProvided("xunicode")) {
2272 // The `xunicode` package officially only supports XeTeX,
2273 // but also works with LuaTeX. We work around its XeTeX test.
2274 if (features.runparams().flavor != OutputParams::XETEX) {
2275 os << "% Pretend to xunicode that we are XeTeX\n"
2276 << "\\def\\XeTeXpicfile{}\n";
2278 os << "\\usepackage{xunicode}\n";
2281 // covington must be loaded after beamerarticle
2282 if (features.isRequired("covington"))
2283 os << "\\usepackage{covington}\n";
2285 // Polyglossia must be loaded last ...
2286 if (use_polyglossia) {
2288 os << "\\usepackage{polyglossia}\n";
2289 // set the main language
2290 os << "\\setdefaultlanguage";
2291 if (!language->polyglossiaOpts().empty())
2292 os << "[" << from_ascii(language->polyglossiaOpts()) << "]";
2293 os << "{" << from_ascii(language->polyglossia()) << "}\n";
2294 // now setup the other languages
2295 set<string> const polylangs =
2296 features.getPolyglossiaLanguages();
2297 for (set<string>::const_iterator mit = polylangs.begin();
2298 mit != polylangs.end() ; ++mit) {
2299 // We do not output the options here; they are output in
2300 // the language switch commands. This is safer if multiple
2301 // varieties are used.
2302 if (*mit == language->polyglossia())
2304 os << "\\setotherlanguage";
2305 os << "{" << from_ascii(*mit) << "}\n";
2309 // ... but before biblatex (see #7065)
2310 if ((features.mustProvide("biblatex")
2311 || features.isRequired("biblatex-chicago"))
2312 && !features.isProvided("biblatex-chicago")
2313 && !features.isProvided("biblatex-natbib")
2314 && !features.isProvided("natbib-internal")
2315 && !features.isProvided("natbib")
2316 && !features.isProvided("jurabib")) {
2317 // The biblatex-chicago package has a differing interface
2318 // it uses a wrapper package and loads styles via fixed options
2319 bool const chicago = features.isRequired("biblatex-chicago");
2322 os << "\\usepackage";
2323 if (!biblatex_bibstyle.empty()
2324 && (biblatex_bibstyle == biblatex_citestyle)
2326 opts = "style=" + biblatex_bibstyle;
2328 } else if (!chicago) {
2329 if (!biblatex_bibstyle.empty()) {
2330 opts = "bibstyle=" + biblatex_bibstyle;
2333 if (!biblatex_citestyle.empty()) {
2334 opts += delim + "citestyle=" + biblatex_citestyle;
2338 if (!multibib.empty() && multibib != "child") {
2339 opts += delim + "refsection=" + multibib;
2342 if (bibtexCommand() == "bibtex8"
2343 || prefixIs(bibtexCommand(), "bibtex8 ")) {
2344 opts += delim + "backend=bibtex8";
2346 } else if (bibtexCommand() == "bibtex"
2347 || prefixIs(bibtexCommand(), "bibtex ")) {
2348 opts += delim + "backend=bibtex";
2351 if (!bib_encoding.empty() && encodings.fromLyXName(bib_encoding)) {
2352 opts += delim + "bibencoding="
2353 + encodings.fromLyXName(bib_encoding)->latexName();
2356 if (!biblio_opts.empty())
2357 opts += delim + biblio_opts;
2359 os << "[" << opts << "]";
2361 os << "{biblatex-chicago}\n";
2363 os << "{biblatex}\n";
2367 // Load custom language package here
2368 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2369 if (lang_package == "default")
2370 os << from_utf8(lyxrc.language_custom_package);
2372 os << from_utf8(lang_package);
2376 // Since menukeys uses catoptions, which does some heavy changes on key-value options,
2377 // it is recommended to load menukeys as the last package (even after hyperref)
2378 if (features.isRequired("menukeys"))
2379 os << "\\usepackage{menukeys}\n";
2381 docstring const i18npreamble =
2382 features.getTClassI18nPreamble(use_babel, use_polyglossia,
2384 if (!i18npreamble.empty())
2385 os << i18npreamble + '\n';
2391 void BufferParams::useClassDefaults()
2393 DocumentClass const & tclass = documentClass();
2395 sides = tclass.sides();
2396 columns = tclass.columns();
2397 pagestyle = tclass.pagestyle();
2398 tablestyle = tclass.tablestyle();
2399 use_default_options = true;
2400 // Only if class has a ToC hierarchy
2401 if (tclass.hasTocLevels()) {
2402 secnumdepth = tclass.secnumdepth();
2403 tocdepth = tclass.tocdepth();
2408 bool BufferParams::hasClassDefaults() const
2410 DocumentClass const & tclass = documentClass();
2412 return sides == tclass.sides()
2413 && columns == tclass.columns()
2414 && pagestyle == tclass.pagestyle()
2415 && tablestyle == tclass.tablestyle()
2416 && use_default_options
2417 && secnumdepth == tclass.secnumdepth()
2418 && tocdepth == tclass.tocdepth();
2422 DocumentClass const & BufferParams::documentClass() const
2428 DocumentClassConstPtr BufferParams::documentClassPtr() const
2434 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2436 // evil, but this function is evil
2437 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2438 invalidateConverterCache();
2442 bool BufferParams::setBaseClass(string const & classname, string const & path)
2444 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2445 LayoutFileList & bcl = LayoutFileList::get();
2446 if (!bcl.haveClass(classname)) {
2448 bformat(_("The layout file:\n"
2450 "could not be found. A default textclass with default\n"
2451 "layouts will be used. LyX will not be able to produce\n"
2453 from_utf8(classname));
2454 frontend::Alert::error(_("Document class not found"), s);
2455 bcl.addEmptyClass(classname);
2458 bool const success = bcl[classname].load(path);
2461 bformat(_("Due to some error in it, the layout file:\n"
2463 "could not be loaded. A default textclass with default\n"
2464 "layouts will be used. LyX will not be able to produce\n"
2466 from_utf8(classname));
2467 frontend::Alert::error(_("Could not load class"), s);
2468 bcl.addEmptyClass(classname);
2471 pimpl_->baseClass_ = classname;
2472 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2477 LayoutFile const * BufferParams::baseClass() const
2479 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2480 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2486 LayoutFileIndex const & BufferParams::baseClassID() const
2488 return pimpl_->baseClass_;
2492 void BufferParams::makeDocumentClass(bool const clone)
2497 invalidateConverterCache();
2498 LayoutModuleList mods;
2499 LayoutModuleList::iterator it = layout_modules_.begin();
2500 LayoutModuleList::iterator en = layout_modules_.end();
2501 for (; it != en; ++it)
2502 mods.push_back(*it);
2504 doc_class_ = getDocumentClass(*baseClass(), mods, cite_engine_, clone);
2506 TextClass::ReturnValues success = TextClass::OK;
2507 if (!forced_local_layout_.empty())
2508 success = doc_class_->read(to_utf8(forced_local_layout_),
2510 if (!local_layout_.empty() &&
2511 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2512 success = doc_class_->read(to_utf8(local_layout_), TextClass::MODULE);
2513 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2514 docstring const msg = _("Error reading internal layout information");
2515 frontend::Alert::warning(_("Read Error"), msg);
2520 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2522 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2526 docstring BufferParams::getLocalLayout(bool forced) const
2529 return from_utf8(doc_class_->forcedLayouts());
2531 return local_layout_;
2535 void BufferParams::setLocalLayout(docstring const & layout, bool forced)
2538 forced_local_layout_ = layout;
2540 local_layout_ = layout;
2544 bool BufferParams::addLayoutModule(string const & modName)
2546 LayoutModuleList::const_iterator it = layout_modules_.begin();
2547 LayoutModuleList::const_iterator end = layout_modules_.end();
2548 for (; it != end; ++it)
2551 layout_modules_.push_back(modName);
2556 string BufferParams::bufferFormat() const
2558 return documentClass().outputFormat();
2562 bool BufferParams::isExportable(string const & format, bool need_viewable) const
2564 FormatList const & formats = exportableFormats(need_viewable);
2565 FormatList::const_iterator fit = formats.begin();
2566 FormatList::const_iterator end = formats.end();
2567 for (; fit != end ; ++fit) {
2568 if ((*fit)->name() == format)
2575 FormatList const & BufferParams::exportableFormats(bool only_viewable) const
2577 FormatList & cached = only_viewable ?
2578 pimpl_->viewableFormatList : pimpl_->exportableFormatList;
2579 bool & valid = only_viewable ?
2580 pimpl_->isViewCacheValid : pimpl_->isExportCacheValid;
2584 vector<string> const backs = backends();
2585 set<string> excludes;
2586 if (useNonTeXFonts) {
2587 excludes.insert("latex");
2588 excludes.insert("pdflatex");
2589 } else if (inputenc != "ascii" && inputenc != "utf8-plain")
2590 // XeTeX with TeX fonts requires input encoding ascii (#10600).
2591 excludes.insert("xetex");
2592 FormatList result = theConverters().getReachable(backs[0], only_viewable,
2594 for (vector<string>::const_iterator it = backs.begin() + 1;
2595 it != backs.end(); ++it) {
2596 FormatList r = theConverters().getReachable(*it, only_viewable,
2598 result.insert(result.end(), r.begin(), r.end());
2600 sort(result.begin(), result.end(), Format::formatSorter);
2607 vector<string> BufferParams::backends() const
2610 string const buffmt = bufferFormat();
2612 // FIXME: Don't hardcode format names here, but use a flag
2613 if (buffmt == "latex") {
2614 if (encoding().package() == Encoding::japanese)
2615 v.push_back("platex");
2617 if (!useNonTeXFonts) {
2618 v.push_back("pdflatex");
2619 v.push_back("latex");
2622 || inputenc == "ascii" || inputenc == "utf8-plain")
2623 v.push_back("xetex");
2624 v.push_back("luatex");
2625 v.push_back("dviluatex");
2628 string rbuffmt = buffmt;
2629 // If we use an OutputFormat in Japanese docs,
2630 // we need special format in order to get the path
2631 // via pLaTeX (#8823)
2632 if (documentClass().hasOutputFormat()
2633 && encoding().package() == Encoding::japanese)
2635 v.push_back(rbuffmt);
2638 v.push_back("xhtml");
2639 v.push_back("text");
2645 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2647 string const dformat = (format.empty() || format == "default") ?
2648 getDefaultOutputFormat() : format;
2649 DefaultFlavorCache::const_iterator it =
2650 default_flavors_.find(dformat);
2652 if (it != default_flavors_.end())
2655 OutputParams::FLAVOR result = OutputParams::LATEX;
2657 // FIXME It'd be better not to hardcode this, but to do
2658 // something with formats.
2659 if (dformat == "xhtml")
2660 result = OutputParams::HTML;
2661 else if (dformat == "text")
2662 result = OutputParams::TEXT;
2663 else if (dformat == "lyx")
2664 result = OutputParams::LYX;
2665 else if (dformat == "pdflatex")
2666 result = OutputParams::PDFLATEX;
2667 else if (dformat == "xetex")
2668 result = OutputParams::XETEX;
2669 else if (dformat == "luatex")
2670 result = OutputParams::LUATEX;
2671 else if (dformat == "dviluatex")
2672 result = OutputParams::DVILUATEX;
2674 // Try to determine flavor of default output format
2675 vector<string> backs = backends();
2676 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2677 // Get shortest path to format
2678 Graph::EdgePath path;
2679 for (auto const & bvar : backs) {
2680 Graph::EdgePath p = theConverters().getPath(bvar, dformat);
2681 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2686 result = theConverters().getFlavor(path);
2689 // cache this flavor
2690 default_flavors_[dformat] = result;
2695 string BufferParams::getDefaultOutputFormat() const
2697 if (!default_output_format.empty()
2698 && default_output_format != "default")
2699 return default_output_format;
2701 FormatList const & formats = exportableFormats(true);
2702 if (formats.empty())
2704 // return the first we find
2705 return formats.front()->name();
2707 if (encoding().package() == Encoding::japanese)
2708 return lyxrc.default_platex_view_format;
2710 return lyxrc.default_otf_view_format;
2711 return lyxrc.default_view_format;
2714 Font const BufferParams::getFont() const
2716 FontInfo f = documentClass().defaultfont();
2717 if (fonts_default_family == "rmdefault")
2718 f.setFamily(ROMAN_FAMILY);
2719 else if (fonts_default_family == "sfdefault")
2720 f.setFamily(SANS_FAMILY);
2721 else if (fonts_default_family == "ttdefault")
2722 f.setFamily(TYPEWRITER_FAMILY);
2723 return Font(f, language);
2727 InsetQuotesParams::QuoteStyle BufferParams::getQuoteStyle(string const & qs) const
2729 return quotesstyletranslator().find(qs);
2733 bool BufferParams::isLatex() const
2735 return documentClass().outputType() == LATEX;
2739 bool BufferParams::isLiterate() const
2741 return documentClass().outputType() == LITERATE;
2745 bool BufferParams::isDocBook() const
2747 return documentClass().outputType() == DOCBOOK;
2751 void BufferParams::readPreamble(Lexer & lex)
2753 if (lex.getString() != "\\begin_preamble")
2754 lyxerr << "Error (BufferParams::readPreamble):"
2755 "consistency check failed." << endl;
2757 preamble = lex.getLongString(from_ascii("\\end_preamble"));
2761 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2763 string const expected = forced ? "\\begin_forced_local_layout" :
2764 "\\begin_local_layout";
2765 if (lex.getString() != expected)
2766 lyxerr << "Error (BufferParams::readLocalLayout):"
2767 "consistency check failed." << endl;
2770 forced_local_layout_ =
2771 lex.getLongString(from_ascii("\\end_forced_local_layout"));
2773 local_layout_ = lex.getLongString(from_ascii("\\end_local_layout"));
2777 bool BufferParams::setLanguage(string const & lang)
2779 Language const *new_language = languages.getLanguage(lang);
2780 if (!new_language) {
2781 // Language lang was not found
2784 language = new_language;
2789 void BufferParams::readLanguage(Lexer & lex)
2791 if (!lex.next()) return;
2793 string const tmptok = lex.getString();
2795 // check if tmptok is part of tex_babel in tex-defs.h
2796 if (!setLanguage(tmptok)) {
2797 // Language tmptok was not found
2798 language = default_language;
2799 lyxerr << "Warning: Setting language `"
2800 << tmptok << "' to `" << language->lang()
2806 void BufferParams::readGraphicsDriver(Lexer & lex)
2811 string const tmptok = lex.getString();
2812 // check if tmptok is part of tex_graphics in tex_defs.h
2815 string const test = tex_graphics[n++];
2817 if (test == tmptok) {
2818 graphics_driver = tmptok;
2823 "Warning: graphics driver `$$Token' not recognized!\n"
2824 " Setting graphics driver to `default'.\n");
2825 graphics_driver = "default";
2832 void BufferParams::readBullets(Lexer & lex)
2837 int const index = lex.getInteger();
2839 int temp_int = lex.getInteger();
2840 user_defined_bullet(index).setFont(temp_int);
2841 temp_bullet(index).setFont(temp_int);
2843 user_defined_bullet(index).setCharacter(temp_int);
2844 temp_bullet(index).setCharacter(temp_int);
2846 user_defined_bullet(index).setSize(temp_int);
2847 temp_bullet(index).setSize(temp_int);
2851 void BufferParams::readBulletsLaTeX(Lexer & lex)
2853 // The bullet class should be able to read this.
2856 int const index = lex.getInteger();
2858 docstring const temp_str = lex.getDocString();
2860 user_defined_bullet(index).setText(temp_str);
2861 temp_bullet(index).setText(temp_str);
2865 void BufferParams::readModules(Lexer & lex)
2867 if (!lex.eatLine()) {
2868 lyxerr << "Error (BufferParams::readModules):"
2869 "Unexpected end of input." << endl;
2873 string mod = lex.getString();
2874 if (mod == "\\end_modules")
2876 addLayoutModule(mod);
2882 void BufferParams::readRemovedModules(Lexer & lex)
2884 if (!lex.eatLine()) {
2885 lyxerr << "Error (BufferParams::readRemovedModules):"
2886 "Unexpected end of input." << endl;
2890 string mod = lex.getString();
2891 if (mod == "\\end_removed_modules")
2893 removed_modules_.push_back(mod);
2896 // now we want to remove any removed modules that were previously
2897 // added. normally, that will be because default modules were added in
2898 // setBaseClass(), which gets called when \textclass is read at the
2899 // start of the read.
2900 list<string>::const_iterator rit = removed_modules_.begin();
2901 list<string>::const_iterator const ren = removed_modules_.end();
2902 for (; rit != ren; ++rit) {
2903 LayoutModuleList::iterator const mit = layout_modules_.begin();
2904 LayoutModuleList::iterator const men = layout_modules_.end();
2905 LayoutModuleList::iterator found = find(mit, men, *rit);
2908 layout_modules_.erase(found);
2913 void BufferParams::readIncludeonly(Lexer & lex)
2915 if (!lex.eatLine()) {
2916 lyxerr << "Error (BufferParams::readIncludeonly):"
2917 "Unexpected end of input." << endl;
2921 string child = lex.getString();
2922 if (child == "\\end_includeonly")
2924 included_children_.push_back(child);
2930 string BufferParams::paperSizeName(PapersizePurpose purpose, string const psize) const
2932 PAPER_SIZE ppsize = psize.empty() ? papersize : papersizetranslator().find(psize);
2935 if (documentClass().pagesize() == "custom")
2936 // could be anything, so don't guess
2938 return paperSizeName(purpose, documentClass().pagesize());
2939 case PAPER_CUSTOM: {
2940 if (purpose == XDVI && !paperwidth.empty() &&
2941 !paperheight.empty()) {
2942 // heightxwidth<unit>
2943 string first = paperwidth;
2944 string second = paperheight;
2945 if (orientation == ORIENTATION_LANDSCAPE)
2948 return first.erase(first.length() - 2)
2954 // dvips and dvipdfm do not know this
2955 if (purpose == DVIPS || purpose == DVIPDFM)
2959 if (purpose == DVIPS || purpose == DVIPDFM)
2963 if (purpose == DVIPS || purpose == DVIPDFM)
2973 if (purpose == DVIPS || purpose == DVIPDFM)
2977 if (purpose == DVIPS || purpose == DVIPDFM)
2981 if (purpose == DVIPS || purpose == DVIPDFM)
2985 if (purpose == DVIPS || purpose == DVIPDFM)
2989 if (purpose == DVIPS || purpose == DVIPDFM)
2993 // dvipdfm does not know this
2994 if (purpose == DVIPDFM)
2998 if (purpose == DVIPDFM)
3002 if (purpose == DVIPS || purpose == DVIPDFM)
3006 if (purpose == DVIPS || purpose == DVIPDFM)
3010 if (purpose == DVIPS || purpose == DVIPDFM)
3014 if (purpose == DVIPS || purpose == DVIPDFM)
3018 if (purpose == DVIPS || purpose == DVIPDFM)
3022 if (purpose == DVIPS || purpose == DVIPDFM)
3026 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 if (purpose == DVIPS || purpose == DVIPDFM)
3054 if (purpose == DVIPS || purpose == DVIPDFM)
3058 if (purpose == DVIPS || purpose == DVIPDFM)
3061 case PAPER_USEXECUTIVE:
3062 // dvipdfm does not know this
3063 if (purpose == DVIPDFM)
3068 case PAPER_USLETTER:
3070 if (purpose == XDVI)
3077 string const BufferParams::dvips_options() const
3081 // If the class loads the geometry package, we do not know which
3082 // paper size is used, since we do not set it (bug 7013).
3083 // Therefore we must not specify any argument here.
3084 // dvips gets the correct paper size via DVI specials in this case
3085 // (if the class uses the geometry package correctly).
3086 if (documentClass().provides("geometry"))
3090 && papersize == PAPER_CUSTOM
3091 && !lyxrc.print_paper_dimension_flag.empty()
3092 && !paperwidth.empty()
3093 && !paperheight.empty()) {
3094 // using a custom papersize
3095 result = lyxrc.print_paper_dimension_flag;
3096 result += ' ' + paperwidth;
3097 result += ',' + paperheight;
3099 string const paper_option = paperSizeName(DVIPS);
3100 if (!paper_option.empty() && (paper_option != "letter" ||
3101 orientation != ORIENTATION_LANDSCAPE)) {
3102 // dvips won't accept -t letter -t landscape.
3103 // In all other cases, include the paper size
3105 result = lyxrc.print_paper_flag;
3106 result += ' ' + paper_option;
3109 if (orientation == ORIENTATION_LANDSCAPE &&
3110 papersize != PAPER_CUSTOM)
3111 result += ' ' + lyxrc.print_landscape_flag;
3116 string const BufferParams::main_font_encoding() const
3118 if (font_encodings().empty()) {
3119 if (ascii_lowercase(language->fontenc(*this)) == "none")
3123 return font_encodings().back();
3127 vector<string> const BufferParams::font_encodings() const
3129 string doc_fontenc = (fontenc == "auto") ? string() : fontenc;
3131 vector<string> fontencs;
3133 // "default" means "no explicit font encoding"
3134 if (doc_fontenc != "default") {
3135 if (!doc_fontenc.empty())
3136 // If we have a custom setting, we use only that!
3137 return getVectorFromString(doc_fontenc);
3138 if (!language->fontenc(*this).empty()
3139 && ascii_lowercase(language->fontenc(*this)) != "none") {
3140 vector<string> fencs = getVectorFromString(language->fontenc(*this));
3141 for (auto & fe : fencs) {
3142 if (find(fontencs.begin(), fontencs.end(), fe) == fontencs.end())
3143 fontencs.push_back(fe);
3152 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
3154 // suppress the babel call if there is no BabelName defined
3155 // for the document language in the lib/languages file and if no
3156 // other languages are used (lang_opts is then empty)
3157 if (lang_opts.empty())
3159 // The prefs may require the languages to
3160 // be submitted to babel itself (not the class).
3162 return "\\usepackage[" + lang_opts + "]{babel}";
3163 return "\\usepackage{babel}";
3167 docstring BufferParams::getGraphicsDriver(string const & package) const
3171 if (package == "geometry") {
3172 if (graphics_driver == "dvips"
3173 || graphics_driver == "dvipdfm"
3174 || graphics_driver == "pdftex"
3175 || graphics_driver == "vtex")
3176 result = from_ascii(graphics_driver);
3177 else if (graphics_driver == "dvipdfmx")
3178 result = from_ascii("dvipdfm");
3185 void BufferParams::writeEncodingPreamble(otexstream & os,
3186 LaTeXFeatures & features) const
3188 // With no-TeX fonts we use utf8-plain without encoding package.
3192 if (inputenc == "auto-legacy") {
3193 string const doc_encoding =
3194 language->encoding()->latexName();
3195 Encoding::Package const package =
3196 language->encoding()->package();
3198 // Create list of inputenc options:
3199 set<string> encoding_set;
3200 // luainputenc fails with more than one encoding
3201 if (features.runparams().flavor != OutputParams::LUATEX
3202 && features.runparams().flavor != OutputParams::DVILUATEX)
3203 // list all input encodings used in the document
3204 encoding_set = features.getEncodingSet(doc_encoding);
3206 // The "japanese" babel-language requires the pLaTeX engine
3207 // which conflicts with "inputenc".
3208 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
3209 if ((!encoding_set.empty() || package == Encoding::inputenc)
3210 && !features.isRequired("japanese")
3211 && !features.isProvided("inputenc")) {
3212 os << "\\usepackage[";
3213 set<string>::const_iterator it = encoding_set.begin();
3214 set<string>::const_iterator const end = encoding_set.end();
3216 os << from_ascii(*it);
3219 for (; it != end; ++it)
3220 os << ',' << from_ascii(*it);
3221 if (package == Encoding::inputenc) {
3222 if (!encoding_set.empty())
3224 os << from_ascii(doc_encoding);
3226 if (features.runparams().flavor == OutputParams::LUATEX
3227 || features.runparams().flavor == OutputParams::DVILUATEX)
3228 os << "]{luainputenc}\n";
3230 os << "]{inputenc}\n";
3232 } else if (inputenc != "auto-legacy-plain") {
3233 switch (encoding().package()) {
3234 case Encoding::none:
3236 case Encoding::japanese:
3237 if (encoding().iconvName() != "UTF-8"
3238 && !features.runparams().isFullUnicode())
3239 // don't default to [utf8]{inputenc} with TeXLive >= 18
3240 os << "\\ifdefined\\UseRawInputEncoding\n"
3241 << " \\UseRawInputEncoding\\fi\n";
3243 case Encoding::inputenc:
3244 // do not load inputenc if japanese is used
3245 // or if the class provides inputenc
3246 if (features.isRequired("japanese")
3247 || features.isProvided("inputenc"))
3249 os << "\\usepackage[" << from_ascii(encoding().latexName());
3250 if (features.runparams().flavor == OutputParams::LUATEX
3251 || features.runparams().flavor == OutputParams::DVILUATEX)
3252 os << "]{luainputenc}\n";
3254 os << "]{inputenc}\n";
3258 if (inputenc == "auto-legacy-plain" || features.isRequired("japanese")) {
3259 // don't default to [utf8]{inputenc} with TeXLive >= 18
3260 os << "\\ifdefined\\UseRawInputEncoding\n";
3261 os << " \\UseRawInputEncoding\\fi\n";
3266 string const BufferParams::parseFontName(string const & name) const
3268 string mangled = name;
3269 size_t const idx = mangled.find('[');
3270 if (idx == string::npos || idx == 0)
3273 return mangled.substr(0, idx - 1);
3277 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3279 if (fontsRoman() == "default" && fontsSans() == "default"
3280 && fontsTypewriter() == "default"
3281 && (fontsMath() == "default" || fontsMath() == "auto"))
3287 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3288 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3289 * Mapping=tex-text option assures TeX ligatures (such as "--")
3290 * are resolved. Note that tt does not use these ligatures.
3292 * -- add more GUI options?
3293 * -- add more fonts (fonts for other scripts)
3294 * -- if there's a way to find out if a font really supports
3295 * OldStyle, enable/disable the widget accordingly.
3297 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3298 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3299 // However, until v.2 (2010/07/11) fontspec only knew
3300 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3301 // was introduced for both XeTeX and LuaTeX (LuaTeX
3302 // didn't understand "Mapping=tex-text", while XeTeX
3303 // understood both. With most recent versions, both
3304 // variants are understood by both engines. However,
3305 // we want to provide support for at least TeXLive 2009
3306 // (for XeTeX; LuaTeX is only supported as of v.2)
3307 // As of 2017/11/03, Babel has its own higher-level
3308 // interface on top of fontspec that is to be used.
3309 bool const babelfonts = features.useBabel()
3310 && features.isAvailable("babel-2017/11/03");
3311 string const texmapping =
3312 (features.runparams().flavor == OutputParams::XETEX) ?
3313 "Mapping=tex-text" : "Ligatures=TeX";
3314 if (fontsRoman() != "default") {
3316 os << "\\babelfont{rm}[";
3318 os << "\\setmainfont[";
3319 if (!font_roman_opts.empty())
3320 os << font_roman_opts << ',';
3322 if (fonts_roman_osf)
3323 os << ",Numbers=OldStyle";
3324 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3326 if (fontsSans() != "default") {
3327 string const sans = parseFontName(fontsSans());
3328 if (fontsSansScale() != 100) {
3330 os << "\\babelfont{sf}";
3332 os << "\\setsansfont";
3334 << float(fontsSansScale()) / 100 << ',';
3336 os << "Numbers=OldStyle,";
3337 if (!font_sans_opts.empty())
3338 os << font_sans_opts << ',';
3339 os << texmapping << "]{"
3343 os << "\\babelfont{sf}[";
3345 os << "\\setsansfont[";
3347 os << "Numbers=OldStyle,";
3348 if (!font_sans_opts.empty())
3349 os << font_sans_opts << ',';
3350 os << texmapping << "]{"
3354 if (fontsTypewriter() != "default") {
3355 string const mono = parseFontName(fontsTypewriter());
3356 if (fontsTypewriterScale() != 100) {
3358 os << "\\babelfont{tt}";
3360 os << "\\setmonofont";
3362 << float(fontsTypewriterScale()) / 100;
3363 if (fonts_typewriter_osf)
3364 os << ",Numbers=OldStyle";
3365 if (!font_typewriter_opts.empty())
3366 os << ',' << font_typewriter_opts;
3371 os << "\\babelfont{tt}";
3373 os << "\\setmonofont";
3374 if (!font_typewriter_opts.empty() || fonts_typewriter_osf) {
3376 if (fonts_typewriter_osf)
3377 os << "Numbers=OldStyle";
3378 if (!font_typewriter_opts.empty()) {
3379 if (fonts_typewriter_osf)
3381 os << font_typewriter_opts;
3385 os << '{' << mono << "}\n";
3392 bool const ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1");
3393 bool const dryrun = features.runparams().dryrun;
3394 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3395 bool const nomath = (fontsMath() == "default");
3398 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3399 dryrun, ot1, complete, fonts_expert_sc, fonts_roman_osf,
3400 nomath, font_roman_opts);
3403 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3404 dryrun, ot1, complete, fonts_expert_sc, fonts_sans_osf,
3405 nomath, font_sans_opts, fontsSansScale());
3407 // MONOSPACED/TYPEWRITER
3408 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3409 dryrun, ot1, complete, fonts_expert_sc, fonts_typewriter_osf,
3410 nomath, font_typewriter_opts, fontsTypewriterScale());
3413 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3414 dryrun, ot1, complete, fonts_expert_sc, fonts_roman_osf,
3421 Encoding const & BufferParams::encoding() const
3423 // Main encoding for LaTeX output.
3425 return *(encodings.fromLyXName("utf8-plain"));
3426 if (inputenc == "auto-legacy" || inputenc == "auto-legacy-plain")
3427 return *language->encoding();
3428 if (inputenc == "utf8" && language->lang() == "japanese")
3429 return *(encodings.fromLyXName("utf8-platex"));
3430 Encoding const * const enc = encodings.fromLyXName(inputenc);
3433 LYXERR0("Unknown inputenc value `" << inputenc
3434 << "'. Using `auto' instead.");
3435 return *language->encoding();
3439 string const & BufferParams::defaultBiblioStyle() const
3441 if (!biblio_style.empty())
3442 return biblio_style;
3444 map<string, string> const & bs = documentClass().defaultBiblioStyle();
3445 auto cit = bs.find(theCiteEnginesList.getTypeAsString(citeEngineType()));
3446 if (cit != bs.end())
3449 return empty_string();
3453 bool const & BufferParams::fullAuthorList() const
3455 return documentClass().fullAuthorList();
3459 string BufferParams::getCiteAlias(string const & s) const
3461 vector<string> commands =
3462 documentClass().citeCommands(citeEngineType());
3463 // If it is a real command, don't treat it as an alias
3464 if (find(commands.begin(), commands.end(), s) != commands.end())
3466 map<string,string> aliases = documentClass().citeCommandAliases();
3467 if (aliases.find(s) != aliases.end())
3473 vector<string> BufferParams::citeCommands() const
3475 static CitationStyle const default_style;
3476 vector<string> commands =
3477 documentClass().citeCommands(citeEngineType());
3478 if (commands.empty())
3479 commands.push_back(default_style.name);
3484 vector<CitationStyle> BufferParams::citeStyles() const
3486 static CitationStyle const default_style;
3487 vector<CitationStyle> styles =
3488 documentClass().citeStyles(citeEngineType());
3490 styles.push_back(default_style);
3495 string const BufferParams::bibtexCommand() const
3497 // Return document-specific setting if available
3498 if (bibtex_command != "default")
3499 return bibtex_command;
3501 // If we have "default" in document settings, consult the prefs
3502 // 1. Japanese (uses a specific processor)
3503 if (encoding().package() == Encoding::japanese) {
3504 if (lyxrc.jbibtex_command != "automatic")
3505 // Return the specified program, if "automatic" is not set
3506 return lyxrc.jbibtex_command;
3507 else if (!useBiblatex()) {
3508 // With classic BibTeX, return pbibtex, jbibtex, bibtex
3509 if (lyxrc.jbibtex_alternatives.find("pbibtex") != lyxrc.jbibtex_alternatives.end())
3511 if (lyxrc.jbibtex_alternatives.find("jbibtex") != lyxrc.jbibtex_alternatives.end())
3516 // 2. All other languages
3517 else if (lyxrc.bibtex_command != "automatic")
3518 // Return the specified program, if "automatic" is not set
3519 return lyxrc.bibtex_command;
3521 // 3. Automatic: find the most suitable for the current cite framework
3522 if (useBiblatex()) {
3523 // For Biblatex, we prefer biber (also for Japanese)
3524 // and fall back to bibtex8 and, as last resort, bibtex
3525 if (lyxrc.bibtex_alternatives.find("biber") != lyxrc.bibtex_alternatives.end())
3527 else if (lyxrc.bibtex_alternatives.find("bibtex8") != lyxrc.bibtex_alternatives.end())
3534 bool BufferParams::useBiblatex() const
3536 return theCiteEnginesList[citeEngine()]->getCiteFramework() == "biblatex";
3540 void BufferParams::invalidateConverterCache() const
3542 pimpl_->isExportCacheValid = false;
3543 pimpl_->isViewCacheValid = false;
3547 // We shouldn't need to reset the params here, since anything
3548 // we need will be recopied.
3549 void BufferParams::copyForAdvFR(const BufferParams & bp)
3551 string const & lang = bp.language->lang();
3553 layout_modules_ = bp.layout_modules_;
3554 string const & doc_class = bp.documentClass().name();
3555 setBaseClass(doc_class);
3559 void BufferParams::setBibFileEncoding(string const & file, string const & enc)
3561 bib_encodings[file] = enc;
3565 string const BufferParams::bibFileEncoding(string const & file) const
3567 if (bib_encodings.find(file) == bib_encodings.end())
3569 return bib_encodings.find(file)->second;