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",
107 // XeTeX with TeX fonts:
108 // run in 8-bit emulation mode and trick `inputenc` into working with XeTeX
109 static docstring const xetex_pre_inputenc = from_ascii(
110 "\\XeTeXinputencoding \"bytes\" % current file\n"
111 "\\XeTeXdefaultencoding \"bytes\" % included files\n"
113 "\\let\\origUmathchar\\Umathchar\n"
114 "\\let\\Umathchar\\@undefined\n");
115 static docstring const xetex_post_inputenc = from_ascii(
116 "\\let\\Umathchar\\origUmathchar\n"
122 // Paragraph separation
123 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
126 ParSepTranslator const init_parseptranslator()
128 ParSepTranslator translator
129 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
130 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
135 ParSepTranslator const & parseptranslator()
137 static ParSepTranslator const translator =
138 init_parseptranslator();
144 typedef Translator<string, InsetQuotesParams::QuoteStyle> QuotesStyleTranslator;
147 QuotesStyleTranslator const init_quotesstyletranslator()
149 QuotesStyleTranslator translator
150 (string_quotes_style[0], InsetQuotesParams::EnglishQuotes);
151 translator.addPair(string_quotes_style[1], InsetQuotesParams::SwedishQuotes);
152 translator.addPair(string_quotes_style[2], InsetQuotesParams::GermanQuotes);
153 translator.addPair(string_quotes_style[3], InsetQuotesParams::PolishQuotes);
154 translator.addPair(string_quotes_style[4], InsetQuotesParams::SwissQuotes);
155 translator.addPair(string_quotes_style[5], InsetQuotesParams::DanishQuotes);
156 translator.addPair(string_quotes_style[6], InsetQuotesParams::PlainQuotes);
157 translator.addPair(string_quotes_style[7], InsetQuotesParams::BritishQuotes);
158 translator.addPair(string_quotes_style[8], InsetQuotesParams::SwedishGQuotes);
159 translator.addPair(string_quotes_style[9], InsetQuotesParams::FrenchQuotes);
160 translator.addPair(string_quotes_style[10], InsetQuotesParams::FrenchINQuotes);
161 translator.addPair(string_quotes_style[11], InsetQuotesParams::RussianQuotes);
162 translator.addPair(string_quotes_style[12], InsetQuotesParams::CJKQuotes);
163 translator.addPair(string_quotes_style[13], InsetQuotesParams::CJKAngleQuotes);
168 QuotesStyleTranslator const & quotesstyletranslator()
170 static QuotesStyleTranslator const translator =
171 init_quotesstyletranslator();
177 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
180 static PaperSizeTranslator initPaperSizeTranslator()
182 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
183 translator.addPair(string_papersize[1], PAPER_CUSTOM);
184 translator.addPair(string_papersize[2], PAPER_USLETTER);
185 translator.addPair(string_papersize[3], PAPER_USLEGAL);
186 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
187 translator.addPair(string_papersize[5], PAPER_A0);
188 translator.addPair(string_papersize[6], PAPER_A1);
189 translator.addPair(string_papersize[7], PAPER_A2);
190 translator.addPair(string_papersize[8], PAPER_A3);
191 translator.addPair(string_papersize[9], PAPER_A4);
192 translator.addPair(string_papersize[10], PAPER_A5);
193 translator.addPair(string_papersize[11], PAPER_A6);
194 translator.addPair(string_papersize[12], PAPER_B0);
195 translator.addPair(string_papersize[13], PAPER_B1);
196 translator.addPair(string_papersize[14], PAPER_B2);
197 translator.addPair(string_papersize[15], PAPER_B3);
198 translator.addPair(string_papersize[16], PAPER_B4);
199 translator.addPair(string_papersize[17], PAPER_B5);
200 translator.addPair(string_papersize[18], PAPER_B6);
201 translator.addPair(string_papersize[19], PAPER_C0);
202 translator.addPair(string_papersize[20], PAPER_C1);
203 translator.addPair(string_papersize[21], PAPER_C2);
204 translator.addPair(string_papersize[22], PAPER_C3);
205 translator.addPair(string_papersize[23], PAPER_C4);
206 translator.addPair(string_papersize[24], PAPER_C5);
207 translator.addPair(string_papersize[25], PAPER_C6);
208 translator.addPair(string_papersize[26], PAPER_JISB0);
209 translator.addPair(string_papersize[27], PAPER_JISB1);
210 translator.addPair(string_papersize[28], PAPER_JISB2);
211 translator.addPair(string_papersize[29], PAPER_JISB3);
212 translator.addPair(string_papersize[30], PAPER_JISB4);
213 translator.addPair(string_papersize[31], PAPER_JISB5);
214 translator.addPair(string_papersize[32], PAPER_JISB6);
219 PaperSizeTranslator const & papersizetranslator()
221 static PaperSizeTranslator const translator =
222 initPaperSizeTranslator();
228 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
231 PaperOrientationTranslator const init_paperorientationtranslator()
233 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
234 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
239 PaperOrientationTranslator const & paperorientationtranslator()
241 static PaperOrientationTranslator const translator =
242 init_paperorientationtranslator();
248 typedef Translator<int, PageSides> SidesTranslator;
251 SidesTranslator const init_sidestranslator()
253 SidesTranslator translator(1, OneSide);
254 translator.addPair(2, TwoSides);
259 SidesTranslator const & sidestranslator()
261 static SidesTranslator const translator = init_sidestranslator();
267 typedef Translator<int, BufferParams::Package> PackageTranslator;
270 PackageTranslator const init_packagetranslator()
272 PackageTranslator translator(0, BufferParams::package_off);
273 translator.addPair(1, BufferParams::package_auto);
274 translator.addPair(2, BufferParams::package_on);
279 PackageTranslator const & packagetranslator()
281 static PackageTranslator const translator =
282 init_packagetranslator();
288 typedef Translator<string, Spacing::Space> SpaceTranslator;
291 SpaceTranslator const init_spacetranslator()
293 SpaceTranslator translator("default", Spacing::Default);
294 translator.addPair("single", Spacing::Single);
295 translator.addPair("onehalf", Spacing::Onehalf);
296 translator.addPair("double", Spacing::Double);
297 translator.addPair("other", Spacing::Other);
302 SpaceTranslator const & spacetranslator()
304 static SpaceTranslator const translator = init_spacetranslator();
309 bool inSystemDir(FileName const & document_dir, string & system_dir)
311 // A document is assumed to be in a system LyX directory (not
312 // necessarily the system directory of the running instance)
313 // if both "configure.py" and "chkconfig.ltx" are found in
314 // either document_dir/../ or document_dir/../../.
315 // If true, the system directory path is returned in system_dir
316 // with a trailing path separator.
318 string const msg = "Checking whether document is in a system dir...";
320 string dir = document_dir.absFileName();
322 for (int i = 0; i < 3; ++i) {
323 dir = addPath(dir, "..");
324 if (!fileSearch(dir, "configure.py").empty() &&
325 !fileSearch(dir, "chkconfig.ltx").empty()) {
326 LYXERR(Debug::FILES, msg << " yes");
327 system_dir = addPath(FileName(dir).realPath(), "");
332 LYXERR(Debug::FILES, msg << " no");
333 system_dir = string();
340 class BufferParams::Impl
345 AuthorList authorlist;
346 BranchList branchlist;
347 Bullet temp_bullets[4];
348 Bullet user_defined_bullets[4];
349 IndicesList indiceslist;
353 /** This is the amount of space used for paragraph_separation "skip",
354 * and for detached paragraphs in "indented" documents.
357 PDFOptions pdfoptions;
358 LayoutFileIndex baseClass_;
359 FormatList exportableFormatList;
360 FormatList viewableFormatList;
361 bool isViewCacheValid;
362 bool isExportCacheValid;
366 BufferParams::Impl::Impl()
367 : defskip(VSpace::MEDSKIP), baseClass_(string("")),
368 isViewCacheValid(false), isExportCacheValid(false)
370 // set initial author
372 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
377 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
380 return new BufferParams::Impl(*ptr);
384 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
390 BufferParams::BufferParams()
393 setBaseClass(defaultBaseclass());
394 cite_engine_ = "basic";
395 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
397 paragraph_separation = ParagraphIndentSeparation;
398 is_math_indent = false;
399 math_numbering_side = DEFAULT;
400 quotes_style = InsetQuotesParams::EnglishQuotes;
401 dynamic_quotes = false;
402 fontsize = "default";
405 papersize = PAPER_DEFAULT;
406 orientation = ORIENTATION_PORTRAIT;
407 use_geometry = false;
408 biblio_style = string();
409 use_bibtopic = false;
412 save_transient_properties = true;
413 track_changes = false;
414 output_changes = false;
415 use_default_options = true;
416 maintain_unincluded_children = false;
419 language = default_language;
421 fonts_roman[0] = "default";
422 fonts_roman[1] = "default";
423 fonts_sans[0] = "default";
424 fonts_sans[1] = "default";
425 fonts_typewriter[0] = "default";
426 fonts_typewriter[1] = "default";
427 fonts_math[0] = "auto";
428 fonts_math[1] = "auto";
429 fonts_default_family = "default";
430 useNonTeXFonts = false;
431 use_microtype = false;
432 use_dash_ligatures = true;
433 fonts_expert_sc = false;
434 fonts_old_figures = false;
435 fonts_sans_scale[0] = 100;
436 fonts_sans_scale[1] = 100;
437 fonts_typewriter_scale[0] = 100;
438 fonts_typewriter_scale[1] = 100;
440 lang_package = "default";
441 graphics_driver = "default";
442 default_output_format = "default";
443 bibtex_command = "default";
444 index_command = "default";
447 listings_params = string();
448 pagestyle = "default";
449 tablestyle = "default";
450 suppress_date = false;
451 justification = true;
452 // no color is the default (white)
453 backgroundcolor = lyx::rgbFromHexName("#ffffff");
454 isbackgroundcolor = false;
455 // no color is the default (black)
456 fontcolor = lyx::rgbFromHexName("#000000");
458 // light gray is the default font color for greyed-out notes
459 notefontcolor = lyx::rgbFromHexName("#cccccc");
460 boxbgcolor = lyx::rgbFromHexName("#ff0000");
461 compressed = lyxrc.save_compressed;
462 for (int iter = 0; iter < 4; ++iter) {
463 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
464 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
467 indiceslist().addDefault(B_("Index"));
468 html_be_strict = false;
469 html_math_output = MathML;
470 html_math_img_scale = 1.0;
471 html_css_as_file = false;
472 display_pixel_ratio = 1.0;
474 shell_escape = false;
480 // map current author
481 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
485 docstring BufferParams::B_(string const & l10n) const
487 LASSERT(language, return from_utf8(l10n));
488 return getMessages(language->code()).get(l10n);
492 BufferParams::Package BufferParams::use_package(std::string const & p) const
494 PackageMap::const_iterator it = use_packages.find(p);
495 if (it == use_packages.end())
501 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
507 map<string, string> const & BufferParams::auto_packages()
509 static map<string, string> packages;
510 if (packages.empty()) {
511 // We could have a race condition here that two threads
512 // discover an empty map at the same time and want to fill
513 // it, but that is no problem, since the same contents is
514 // filled in twice then. Having the locker inside the
515 // packages.empty() condition has the advantage that we
516 // don't need the mutex overhead for simple reading.
518 Mutex::Locker locker(&mutex);
519 // adding a package here implies a file format change!
520 packages["amsmath"] =
521 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
522 packages["amssymb"] =
523 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
525 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
527 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
528 packages["mathdots"] =
529 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
530 packages["mathtools"] =
531 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
533 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
534 packages["stackrel"] =
535 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
536 packages["stmaryrd"] =
537 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");
538 packages["undertilde"] =
539 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
545 bool BufferParams::useBibtopic() const
549 return (use_bibtopic || (!multibib.empty() && multibib != "child"));
553 AuthorList & BufferParams::authors()
555 return pimpl_->authorlist;
559 AuthorList const & BufferParams::authors() const
561 return pimpl_->authorlist;
565 void BufferParams::addAuthor(Author a)
567 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
571 BranchList & BufferParams::branchlist()
573 return pimpl_->branchlist;
577 BranchList const & BufferParams::branchlist() const
579 return pimpl_->branchlist;
583 IndicesList & BufferParams::indiceslist()
585 return pimpl_->indiceslist;
589 IndicesList const & BufferParams::indiceslist() const
591 return pimpl_->indiceslist;
595 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
597 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
598 return pimpl_->temp_bullets[index];
602 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
604 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
605 return pimpl_->temp_bullets[index];
609 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
611 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
612 return pimpl_->user_defined_bullets[index];
616 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
618 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
619 return pimpl_->user_defined_bullets[index];
623 Spacing & BufferParams::spacing()
625 return pimpl_->spacing;
629 Spacing const & BufferParams::spacing() const
631 return pimpl_->spacing;
635 PDFOptions & BufferParams::pdfoptions()
637 return pimpl_->pdfoptions;
641 PDFOptions const & BufferParams::pdfoptions() const
643 return pimpl_->pdfoptions;
647 Length const & BufferParams::getMathIndent() const
649 return pimpl_->mathindent;
653 void BufferParams::setMathIndent(Length const & indent)
655 pimpl_->mathindent = indent;
659 Length const & BufferParams::getParIndent() const
661 return pimpl_->parindent;
665 void BufferParams::setParIndent(Length const & indent)
667 pimpl_->parindent = indent;
671 VSpace const & BufferParams::getDefSkip() const
673 return pimpl_->defskip;
677 void BufferParams::setDefSkip(VSpace const & vs)
679 // DEFSKIP will cause an infinite loop
680 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
681 pimpl_->defskip = vs;
685 BufferParams::MathNumber BufferParams::getMathNumber() const
687 if (math_numbering_side != DEFAULT)
688 return math_numbering_side;
689 // FIXME: do not hardcode language here
690 else if (language->lang() == "arabic_arabi"
691 || documentClass().provides("leqno"))
698 string BufferParams::readToken(Lexer & lex, string const & token,
699 FileName const & filepath)
703 if (token == "\\textclass") {
705 string const classname = lex.getString();
706 // if there exists a local layout file, ignore the system one
707 // NOTE: in this case, the textclass (.cls file) is assumed to
710 LayoutFileList & bcl = LayoutFileList::get();
711 if (!filepath.empty()) {
712 // If classname is an absolute path, the document is
713 // using a local layout file which could not be accessed
714 // by a relative path. In this case the path is correct
715 // even if the document was moved to a different
716 // location. However, we will have a problem if the
717 // document was generated on a different platform.
718 bool isabsolute = FileName::isAbsolute(classname);
719 string const classpath = onlyPath(classname);
720 string const path = isabsolute ? classpath
721 : FileName(addPath(filepath.absFileName(),
722 classpath)).realPath();
723 string const oldpath = isabsolute ? string()
724 : FileName(addPath(origin, classpath)).realPath();
725 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
727 // that returns non-empty if a "local" layout file is found.
729 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
730 from_utf8(filepath.absFileName())));
733 setBaseClass(onlyFileName(tcp));
735 setBaseClass(onlyFileName(classname));
736 // We assume that a tex class exists for local or unknown
737 // layouts so this warning, will only be given for system layouts.
738 if (!baseClass()->isTeXClassAvailable()) {
739 docstring const desc =
740 translateIfPossible(from_utf8(baseClass()->description()));
741 docstring const prereqs =
742 from_utf8(baseClass()->prerequisites());
743 docstring const msg =
744 bformat(_("The selected document class\n"
746 "requires external files that are not available.\n"
747 "The document class can still be used, but the\n"
748 "document cannot be compiled until the following\n"
749 "prerequisites are installed:\n"
751 "See section 3.1.2.2 (Class Availability) of the\n"
752 "User's Guide for more information."), desc, prereqs);
753 frontend::Alert::warning(_("Document class not available"),
756 } else if (token == "\\save_transient_properties") {
757 lex >> save_transient_properties;
758 } else if (token == "\\origin") {
760 origin = lex.getString();
761 string const sysdirprefix = "/systemlyxdir/";
762 if (prefixIs(origin, sysdirprefix)) {
764 if (inSystemDir(filepath, docsys))
765 origin.replace(0, sysdirprefix.length() - 1, docsys);
767 origin.replace(0, sysdirprefix.length() - 1,
768 package().system_support().absFileName());
770 } else if (token == "\\begin_preamble") {
772 } else if (token == "\\begin_local_layout") {
773 readLocalLayout(lex, false);
774 } else if (token == "\\begin_forced_local_layout") {
775 readLocalLayout(lex, true);
776 } else if (token == "\\begin_modules") {
778 } else if (token == "\\begin_removed_modules") {
779 readRemovedModules(lex);
780 } else if (token == "\\begin_includeonly") {
781 readIncludeonly(lex);
782 } else if (token == "\\maintain_unincluded_children") {
783 lex >> maintain_unincluded_children;
784 } else if (token == "\\options") {
786 options = lex.getString();
787 } else if (token == "\\use_default_options") {
788 lex >> use_default_options;
789 } else if (token == "\\master") {
791 master = lex.getString();
792 if (!filepath.empty() && FileName::isAbsolute(origin)) {
793 bool const isabs = FileName::isAbsolute(master);
794 FileName const abspath(isabs ? master : origin + master);
795 bool const moved = filepath != FileName(origin);
796 if (moved && abspath.exists()) {
797 docstring const path = isabs
799 : from_utf8(abspath.realPath());
800 docstring const refpath =
801 from_utf8(filepath.absFileName());
802 master = to_utf8(makeRelPath(path, refpath));
805 } else if (token == "\\suppress_date") {
806 lex >> suppress_date;
807 } else if (token == "\\justification") {
808 lex >> justification;
809 } else if (token == "\\language") {
811 } else if (token == "\\language_package") {
813 lang_package = lex.getString();
814 } else if (token == "\\inputencoding") {
816 } else if (token == "\\graphics") {
817 readGraphicsDriver(lex);
818 } else if (token == "\\default_output_format") {
819 lex >> default_output_format;
820 } else if (token == "\\bibtex_command") {
822 bibtex_command = lex.getString();
823 } else if (token == "\\index_command") {
825 index_command = lex.getString();
826 } else if (token == "\\fontencoding") {
828 fontenc = lex.getString();
829 } else if (token == "\\font_roman") {
830 lex >> fonts_roman[0];
831 lex >> fonts_roman[1];
832 } else if (token == "\\font_sans") {
833 lex >> fonts_sans[0];
834 lex >> fonts_sans[1];
835 } else if (token == "\\font_typewriter") {
836 lex >> fonts_typewriter[0];
837 lex >> fonts_typewriter[1];
838 } else if (token == "\\font_math") {
839 lex >> fonts_math[0];
840 lex >> fonts_math[1];
841 } else if (token == "\\font_default_family") {
842 lex >> fonts_default_family;
843 } else if (token == "\\use_non_tex_fonts") {
844 lex >> useNonTeXFonts;
845 } else if (token == "\\font_sc") {
846 lex >> fonts_expert_sc;
847 } else if (token == "\\font_osf") {
848 lex >> fonts_old_figures;
849 } else if (token == "\\font_roman_opts") {
850 lex >> font_roman_opts;
851 } else if (token == "\\font_sf_scale") {
852 lex >> fonts_sans_scale[0];
853 lex >> fonts_sans_scale[1];
854 } else if (token == "\\font_sans_opts") {
855 lex >> font_sans_opts;
856 } else if (token == "\\font_tt_scale") {
857 lex >> fonts_typewriter_scale[0];
858 lex >> fonts_typewriter_scale[1];
859 } else if (token == "\\font_typewriter_opts") {
860 lex >> font_typewriter_opts;
861 } else if (token == "\\font_cjk") {
863 } else if (token == "\\use_microtype") {
864 lex >> use_microtype;
865 } else if (token == "\\use_dash_ligatures") {
866 lex >> use_dash_ligatures;
867 } else if (token == "\\paragraph_separation") {
870 paragraph_separation = parseptranslator().find(parsep);
871 } else if (token == "\\paragraph_indentation") {
873 string parindent = lex.getString();
874 if (parindent == "default")
875 pimpl_->parindent = Length();
877 pimpl_->parindent = Length(parindent);
878 } else if (token == "\\defskip") {
880 string const defskip = lex.getString();
881 pimpl_->defskip = VSpace(defskip);
882 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
884 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
885 } else if (token == "\\is_math_indent") {
886 lex >> is_math_indent;
887 } else if (token == "\\math_indentation") {
889 string mathindent = lex.getString();
890 if (mathindent == "default")
891 pimpl_->mathindent = Length();
893 pimpl_->mathindent = Length(mathindent);
894 } else if (token == "\\math_numbering_side") {
898 math_numbering_side = LEFT;
899 else if (tmp == "right")
900 math_numbering_side = RIGHT;
902 math_numbering_side = DEFAULT;
903 } else if (token == "\\quotes_style") {
906 quotes_style = quotesstyletranslator().find(qstyle);
907 } else if (token == "\\dynamic_quotes") {
908 lex >> dynamic_quotes;
909 } else if (token == "\\papersize") {
912 papersize = papersizetranslator().find(ppsize);
913 } else if (token == "\\use_geometry") {
915 } else if (token == "\\use_package") {
920 use_package(package, packagetranslator().find(use));
921 } else if (token == "\\cite_engine") {
923 cite_engine_ = lex.getString();
924 } else if (token == "\\cite_engine_type") {
927 cite_engine_type_ = theCiteEnginesList.getType(engine_type);
928 } else if (token == "\\biblio_style") {
930 biblio_style = lex.getString();
931 } else if (token == "\\biblio_options") {
933 biblio_opts = trim(lex.getString());
934 } else if (token == "\\biblatex_bibstyle") {
936 biblatex_bibstyle = trim(lex.getString());
937 } else if (token == "\\biblatex_citestyle") {
939 biblatex_citestyle = trim(lex.getString());
940 } else if (token == "\\use_bibtopic") {
942 } else if (token == "\\multibib") {
944 } else if (token == "\\use_indices") {
946 } else if (token == "\\tracking_changes") {
947 lex >> track_changes;
948 } else if (token == "\\output_changes") {
949 lex >> output_changes;
950 } else if (token == "\\branch") {
952 docstring branch = lex.getDocString();
953 branchlist().add(branch);
956 string const tok = lex.getString();
957 if (tok == "\\end_branch")
959 Branch * branch_ptr = branchlist().find(branch);
960 if (tok == "\\selected") {
963 branch_ptr->setSelected(lex.getInteger());
965 if (tok == "\\filename_suffix") {
968 branch_ptr->setFileNameSuffix(lex.getInteger());
970 if (tok == "\\color") {
972 string color = lex.getString();
974 branch_ptr->setColor(color);
975 // Update also the Color table:
977 color = lcolor.getX11Name(Color_background);
979 lcolor.setColor(to_utf8(branch), color);
982 } else if (token == "\\index") {
984 docstring index = lex.getDocString();
986 indiceslist().add(index);
989 string const tok = lex.getString();
990 if (tok == "\\end_index")
992 Index * index_ptr = indiceslist().find(index);
993 if (tok == "\\shortcut") {
995 shortcut = lex.getDocString();
997 index_ptr->setShortcut(shortcut);
999 if (tok == "\\color") {
1001 string color = lex.getString();
1003 index_ptr->setColor(color);
1004 // Update also the Color table:
1005 if (color == "none")
1006 color = lcolor.getX11Name(Color_background);
1008 if (!shortcut.empty())
1009 lcolor.setColor(to_utf8(shortcut), color);
1012 } else if (token == "\\author") {
1014 istringstream ss(lex.getString());
1018 } else if (token == "\\paperorientation") {
1021 orientation = paperorientationtranslator().find(orient);
1022 } else if (token == "\\backgroundcolor") {
1024 backgroundcolor = lyx::rgbFromHexName(lex.getString());
1025 isbackgroundcolor = true;
1026 } else if (token == "\\fontcolor") {
1028 fontcolor = lyx::rgbFromHexName(lex.getString());
1030 } else if (token == "\\notefontcolor") {
1032 string color = lex.getString();
1033 notefontcolor = lyx::rgbFromHexName(color);
1034 lcolor.setColor("notefontcolor", color);
1035 } else if (token == "\\boxbgcolor") {
1037 string color = lex.getString();
1038 boxbgcolor = lyx::rgbFromHexName(color);
1039 lcolor.setColor("boxbgcolor", color);
1040 } else if (token == "\\paperwidth") {
1042 } else if (token == "\\paperheight") {
1044 } else if (token == "\\leftmargin") {
1046 } else if (token == "\\topmargin") {
1048 } else if (token == "\\rightmargin") {
1050 } else if (token == "\\bottommargin") {
1051 lex >> bottommargin;
1052 } else if (token == "\\headheight") {
1054 } else if (token == "\\headsep") {
1056 } else if (token == "\\footskip") {
1058 } else if (token == "\\columnsep") {
1060 } else if (token == "\\paperfontsize") {
1062 } else if (token == "\\papercolumns") {
1064 } else if (token == "\\listings_params") {
1067 listings_params = InsetListingsParams(par).params();
1068 } else if (token == "\\papersides") {
1071 sides = sidestranslator().find(psides);
1072 } else if (token == "\\paperpagestyle") {
1074 } else if (token == "\\tablestyle") {
1076 } else if (token == "\\bullet") {
1078 } else if (token == "\\bulletLaTeX") {
1079 readBulletsLaTeX(lex);
1080 } else if (token == "\\secnumdepth") {
1082 } else if (token == "\\tocdepth") {
1084 } else if (token == "\\spacing") {
1088 if (nspacing == "other") {
1091 spacing().set(spacetranslator().find(nspacing), tmp_val);
1092 } else if (token == "\\float_placement") {
1093 lex >> float_placement;
1094 } else if (token == "\\float_alignment") {
1095 lex >> float_alignment;
1097 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
1098 string toktmp = pdfoptions().readToken(lex, token);
1099 if (!toktmp.empty()) {
1100 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
1104 } else if (token == "\\html_math_output") {
1107 html_math_output = static_cast<MathOutput>(temp);
1108 } else if (token == "\\html_be_strict") {
1109 lex >> html_be_strict;
1110 } else if (token == "\\html_css_as_file") {
1111 lex >> html_css_as_file;
1112 } else if (token == "\\html_math_img_scale") {
1113 lex >> html_math_img_scale;
1114 } else if (token == "\\html_latex_start") {
1116 html_latex_start = lex.getString();
1117 } else if (token == "\\html_latex_end") {
1119 html_latex_end = lex.getString();
1120 } else if (token == "\\output_sync") {
1122 } else if (token == "\\output_sync_macro") {
1123 lex >> output_sync_macro;
1124 } else if (token == "\\use_refstyle") {
1125 lex >> use_refstyle;
1126 } else if (token == "\\use_minted") {
1128 } else if (token == "\\use_lineno") {
1130 } else if (token == "\\lineno_options") {
1132 lineno_opts = trim(lex.getString());
1134 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1144 // Quote argument if it contains spaces
1145 string quoteIfNeeded(string const & str) {
1146 if (contains(str, ' '))
1147 return "\"" + str + "\"";
1153 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1155 // The top of the file is written by the buffer.
1156 // Prints out the buffer info into the .lyx file given by file
1158 os << "\\save_transient_properties "
1159 << convert<string>(save_transient_properties) << '\n';
1161 // the document directory (must end with a path separator)
1162 // realPath() is used to resolve symlinks, while addPath(..., "")
1163 // ensures a trailing path separator.
1165 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1166 string const sysdir = inSystemDir(FileName(filepath), docsys) ? docsys
1167 : addPath(package().system_support().realPath(), "");
1168 string const relpath =
1169 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1170 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1171 filepath = addPath("/systemlyxdir", relpath);
1172 else if (!save_transient_properties || !lyxrc.save_origin)
1173 filepath = "unavailable";
1174 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1177 os << "\\textclass "
1178 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1179 baseClass()->name()), "layout"))
1182 // then the preamble
1183 if (!preamble.empty()) {
1184 // remove '\n' from the end of preamble
1185 docstring const tmppreamble = rtrim(preamble, "\n");
1186 os << "\\begin_preamble\n"
1187 << to_utf8(tmppreamble)
1188 << "\n\\end_preamble\n";
1192 if (!options.empty()) {
1193 os << "\\options " << options << '\n';
1196 // use the class options defined in the layout?
1197 os << "\\use_default_options "
1198 << convert<string>(use_default_options) << "\n";
1200 // the master document
1201 if (!master.empty()) {
1202 os << "\\master " << master << '\n';
1206 if (!removed_modules_.empty()) {
1207 os << "\\begin_removed_modules" << '\n';
1208 list<string>::const_iterator it = removed_modules_.begin();
1209 list<string>::const_iterator en = removed_modules_.end();
1210 for (; it != en; ++it)
1212 os << "\\end_removed_modules" << '\n';
1216 if (!layout_modules_.empty()) {
1217 os << "\\begin_modules" << '\n';
1218 LayoutModuleList::const_iterator it = layout_modules_.begin();
1219 LayoutModuleList::const_iterator en = layout_modules_.end();
1220 for (; it != en; ++it)
1222 os << "\\end_modules" << '\n';
1226 if (!included_children_.empty()) {
1227 os << "\\begin_includeonly" << '\n';
1228 list<string>::const_iterator it = included_children_.begin();
1229 list<string>::const_iterator en = included_children_.end();
1230 for (; it != en; ++it)
1232 os << "\\end_includeonly" << '\n';
1234 os << "\\maintain_unincluded_children "
1235 << convert<string>(maintain_unincluded_children) << '\n';
1237 // local layout information
1238 docstring const local_layout = getLocalLayout(false);
1239 if (!local_layout.empty()) {
1240 // remove '\n' from the end
1241 docstring const tmplocal = rtrim(local_layout, "\n");
1242 os << "\\begin_local_layout\n"
1243 << to_utf8(tmplocal)
1244 << "\n\\end_local_layout\n";
1246 docstring const forced_local_layout = getLocalLayout(true);
1247 if (!forced_local_layout.empty()) {
1248 // remove '\n' from the end
1249 docstring const tmplocal = rtrim(forced_local_layout, "\n");
1250 os << "\\begin_forced_local_layout\n"
1251 << to_utf8(tmplocal)
1252 << "\n\\end_forced_local_layout\n";
1255 // then the text parameters
1256 if (language != ignore_language)
1257 os << "\\language " << language->lang() << '\n';
1258 os << "\\language_package " << lang_package
1259 << "\n\\inputencoding " << inputenc
1260 << "\n\\fontencoding " << fontenc
1261 << "\n\\font_roman \"" << fonts_roman[0]
1262 << "\" \"" << fonts_roman[1] << '"'
1263 << "\n\\font_sans \"" << fonts_sans[0]
1264 << "\" \"" << fonts_sans[1] << '"'
1265 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1266 << "\" \"" << fonts_typewriter[1] << '"'
1267 << "\n\\font_math \"" << fonts_math[0]
1268 << "\" \"" << fonts_math[1] << '"'
1269 << "\n\\font_default_family " << fonts_default_family
1270 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1271 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1272 << "\n\\font_osf " << convert<string>(fonts_old_figures);
1273 if (!font_roman_opts.empty())
1274 os << "\n\\font_roman_opts \"" << font_roman_opts << "\"";
1275 os << "\n\\font_sf_scale " << fonts_sans_scale[0]
1276 << ' ' << fonts_sans_scale[1];
1277 if (!font_sans_opts.empty())
1278 os << "\n\\font_sans_opts \"" << font_sans_opts << "\"";
1279 os << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1280 << ' ' << fonts_typewriter_scale[1];
1281 if (!font_typewriter_opts.empty())
1282 os << "\n\\font_typewriter_opts \"" << font_typewriter_opts << "\"";
1284 if (!fonts_cjk.empty())
1285 os << "\\font_cjk " << fonts_cjk << '\n';
1286 os << "\\use_microtype " << convert<string>(use_microtype) << '\n';
1287 os << "\\use_dash_ligatures " << convert<string>(use_dash_ligatures) << '\n';
1288 os << "\\graphics " << graphics_driver << '\n';
1289 os << "\\default_output_format " << default_output_format << '\n';
1290 os << "\\output_sync " << output_sync << '\n';
1291 if (!output_sync_macro.empty())
1292 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1293 os << "\\bibtex_command " << bibtex_command << '\n';
1294 os << "\\index_command " << index_command << '\n';
1296 if (!float_placement.empty())
1297 os << "\\float_placement " << float_placement << '\n';
1298 if (!float_alignment.empty())
1299 os << "\\float_alignment " << float_alignment << '\n';
1300 os << "\\paperfontsize " << fontsize << '\n';
1302 spacing().writeFile(os);
1303 pdfoptions().writeFile(os);
1305 os << "\\papersize " << string_papersize[papersize]
1306 << "\n\\use_geometry " << convert<string>(use_geometry);
1307 map<string, string> const & packages = auto_packages();
1308 for (map<string, string>::const_iterator it = packages.begin();
1309 it != packages.end(); ++it)
1310 os << "\n\\use_package " << it->first << ' '
1311 << use_package(it->first);
1313 os << "\n\\cite_engine ";
1315 if (!cite_engine_.empty())
1320 os << "\n\\cite_engine_type " << theCiteEnginesList.getTypeAsString(cite_engine_type_);
1322 if (!biblio_style.empty())
1323 os << "\n\\biblio_style " << biblio_style;
1324 if (!biblio_opts.empty())
1325 os << "\n\\biblio_options " << biblio_opts;
1326 if (!biblatex_bibstyle.empty())
1327 os << "\n\\biblatex_bibstyle " << biblatex_bibstyle;
1328 if (!biblatex_citestyle.empty())
1329 os << "\n\\biblatex_citestyle " << biblatex_citestyle;
1330 if (!multibib.empty())
1331 os << "\n\\multibib " << multibib;
1333 os << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1334 << "\n\\use_indices " << convert<string>(use_indices)
1335 << "\n\\paperorientation " << string_orientation[orientation]
1336 << "\n\\suppress_date " << convert<string>(suppress_date)
1337 << "\n\\justification " << convert<string>(justification)
1338 << "\n\\use_refstyle " << use_refstyle
1339 << "\n\\use_minted " << use_minted
1340 << "\n\\use_lineno " << use_lineno
1343 if (!lineno_opts.empty())
1344 os << "\\lineno_options " << lineno_opts << '\n';
1346 if (isbackgroundcolor == true)
1347 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1348 if (isfontcolor == true)
1349 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1350 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1351 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1352 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1353 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1355 BranchList::const_iterator it = branchlist().begin();
1356 BranchList::const_iterator end = branchlist().end();
1357 for (; it != end; ++it) {
1358 os << "\\branch " << to_utf8(it->branch())
1359 << "\n\\selected " << it->isSelected()
1360 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1361 << "\n\\color " << lyx::X11hexname(it->color())
1366 IndicesList::const_iterator iit = indiceslist().begin();
1367 IndicesList::const_iterator iend = indiceslist().end();
1368 for (; iit != iend; ++iit) {
1369 os << "\\index " << to_utf8(iit->index())
1370 << "\n\\shortcut " << to_utf8(iit->shortcut())
1371 << "\n\\color " << lyx::X11hexname(iit->color())
1376 if (!paperwidth.empty())
1377 os << "\\paperwidth "
1378 << VSpace(paperwidth).asLyXCommand() << '\n';
1379 if (!paperheight.empty())
1380 os << "\\paperheight "
1381 << VSpace(paperheight).asLyXCommand() << '\n';
1382 if (!leftmargin.empty())
1383 os << "\\leftmargin "
1384 << VSpace(leftmargin).asLyXCommand() << '\n';
1385 if (!topmargin.empty())
1386 os << "\\topmargin "
1387 << VSpace(topmargin).asLyXCommand() << '\n';
1388 if (!rightmargin.empty())
1389 os << "\\rightmargin "
1390 << VSpace(rightmargin).asLyXCommand() << '\n';
1391 if (!bottommargin.empty())
1392 os << "\\bottommargin "
1393 << VSpace(bottommargin).asLyXCommand() << '\n';
1394 if (!headheight.empty())
1395 os << "\\headheight "
1396 << VSpace(headheight).asLyXCommand() << '\n';
1397 if (!headsep.empty())
1399 << VSpace(headsep).asLyXCommand() << '\n';
1400 if (!footskip.empty())
1402 << VSpace(footskip).asLyXCommand() << '\n';
1403 if (!columnsep.empty())
1404 os << "\\columnsep "
1405 << VSpace(columnsep).asLyXCommand() << '\n';
1406 os << "\\secnumdepth " << secnumdepth
1407 << "\n\\tocdepth " << tocdepth
1408 << "\n\\paragraph_separation "
1409 << string_paragraph_separation[paragraph_separation];
1410 if (!paragraph_separation)
1411 os << "\n\\paragraph_indentation "
1412 << (getParIndent().empty() ? "default" : getParIndent().asString());
1414 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1415 os << "\n\\is_math_indent " << is_math_indent;
1417 os << "\n\\math_indentation "
1418 << (getMathIndent().empty() ? "default" : getMathIndent().asString());
1419 os << "\n\\math_numbering_side ";
1420 switch(math_numbering_side) {
1430 os << "\n\\quotes_style "
1431 << string_quotes_style[quotes_style]
1432 << "\n\\dynamic_quotes " << dynamic_quotes
1433 << "\n\\papercolumns " << columns
1434 << "\n\\papersides " << sides
1435 << "\n\\paperpagestyle " << pagestyle
1436 << "\n\\tablestyle " << tablestyle << '\n';
1437 if (!listings_params.empty())
1438 os << "\\listings_params \"" <<
1439 InsetListingsParams(listings_params).encodedString() << "\"\n";
1440 for (int i = 0; i < 4; ++i) {
1441 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1442 if (user_defined_bullet(i).getFont() != -1) {
1443 os << "\\bullet " << i << " "
1444 << user_defined_bullet(i).getFont() << " "
1445 << user_defined_bullet(i).getCharacter() << " "
1446 << user_defined_bullet(i).getSize() << "\n";
1450 os << "\\bulletLaTeX " << i << " \""
1451 << lyx::to_ascii(user_defined_bullet(i).getText())
1457 os << "\\tracking_changes "
1458 << (save_transient_properties ? convert<string>(track_changes) : "false")
1461 os << "\\output_changes "
1462 << (save_transient_properties ? convert<string>(output_changes) : "false")
1465 os << "\\html_math_output " << html_math_output << '\n'
1466 << "\\html_css_as_file " << html_css_as_file << '\n'
1467 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1469 if (html_math_img_scale != 1.0)
1470 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1471 if (!html_latex_start.empty())
1472 os << "\\html_latex_start " << html_latex_start << '\n';
1473 if (!html_latex_end.empty())
1474 os << "\\html_latex_end " << html_latex_end << '\n';
1476 os << pimpl_->authorlist;
1480 void BufferParams::validate(LaTeXFeatures & features) const
1482 features.require(documentClass().requires());
1484 if (columns > 1 && language->rightToLeft())
1485 features.require("rtloutputdblcol");
1487 if (output_changes) {
1488 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1489 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1490 LaTeXFeatures::isAvailable("xcolor");
1492 switch (features.runparams().flavor) {
1493 case OutputParams::LATEX:
1494 case OutputParams::DVILUATEX:
1496 features.require("ct-dvipost");
1497 features.require("dvipost");
1498 } else if (xcolorulem) {
1499 features.require("ct-xcolor-ulem");
1500 features.require("ulem");
1501 features.require("xcolor");
1503 features.require("ct-none");
1506 case OutputParams::LUATEX:
1507 case OutputParams::PDFLATEX:
1508 case OutputParams::XETEX:
1510 features.require("ct-xcolor-ulem");
1511 features.require("ulem");
1512 features.require("xcolor");
1513 // improves color handling in PDF output
1514 features.require("pdfcolmk");
1516 features.require("ct-none");
1524 // Floats with 'Here definitely' as default setting.
1525 if (float_placement.find('H') != string::npos)
1526 features.require("float");
1528 for (PackageMap::const_iterator it = use_packages.begin();
1529 it != use_packages.end(); ++it) {
1530 if (it->first == "amsmath") {
1531 // AMS Style is at document level
1532 if (it->second == package_on ||
1533 features.isProvided("amsmath"))
1534 features.require(it->first);
1535 } else if (it->second == package_on)
1536 features.require(it->first);
1539 // Document-level line spacing
1540 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1541 features.require("setspace");
1543 // the bullet shapes are buffer level not paragraph level
1544 // so they are tested here
1545 for (int i = 0; i < 4; ++i) {
1546 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1548 int const font = user_defined_bullet(i).getFont();
1550 int const c = user_defined_bullet(i).getCharacter();
1556 features.require("latexsym");
1558 } else if (font == 1) {
1559 features.require("amssymb");
1560 } else if (font >= 2 && font <= 5) {
1561 features.require("pifont");
1565 if (pdfoptions().use_hyperref) {
1566 features.require("hyperref");
1567 // due to interferences with babel and hyperref, the color package has to
1568 // be loaded after hyperref when hyperref is used with the colorlinks
1569 // option, see http://www.lyx.org/trac/ticket/5291
1570 if (pdfoptions().colorlinks)
1571 features.require("color");
1573 if (!listings_params.empty()) {
1574 // do not test validity because listings_params is
1575 // supposed to be valid
1577 InsetListingsParams(listings_params).separatedParams(true);
1578 // we can't support all packages, but we should load the color package
1579 if (par.find("\\color", 0) != string::npos)
1580 features.require("color");
1583 // some languages are only available via polyglossia
1584 if (features.hasPolyglossiaExclusiveLanguages())
1585 features.require("polyglossia");
1587 if (useNonTeXFonts && fontsMath() != "auto")
1588 features.require("unicode-math");
1591 features.require("microtype");
1593 if (!language->requires().empty())
1594 features.require(language->requires());
1598 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1599 FileName const & filepath) const
1601 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1602 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1603 // \RequirePackage to do so, rather than the normal \usepackage
1604 // Do not try to load any other package before the document class, unless you
1605 // have a thorough understanding of the LATEX internals and know exactly what you
1607 if (features.mustProvide("fix-cm"))
1608 os << "\\RequirePackage{fix-cm}\n";
1609 // Likewise for fixltx2e. If other packages conflict with this policy,
1610 // treat it as a package bug (and report it!)
1611 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1612 if (features.mustProvide("fixltx2e"))
1613 os << "\\RequirePackage{fixltx2e}\n";
1615 os << "\\documentclass";
1617 DocumentClass const & tclass = documentClass();
1619 ostringstream clsoptions; // the document class options.
1621 if (tokenPos(tclass.opt_fontsize(),
1622 '|', fontsize) >= 0) {
1623 // only write if existing in list (and not default)
1624 clsoptions << fontsize << "pt,";
1627 // all paper sizes except of A4, A5, B5 and the US sizes need the
1629 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1630 && papersize != PAPER_USLETTER
1631 && papersize != PAPER_USLEGAL
1632 && papersize != PAPER_USEXECUTIVE
1633 && papersize != PAPER_A4
1634 && papersize != PAPER_A5
1635 && papersize != PAPER_B5;
1637 if (!use_geometry) {
1638 switch (papersize) {
1640 clsoptions << "a4paper,";
1642 case PAPER_USLETTER:
1643 clsoptions << "letterpaper,";
1646 clsoptions << "a5paper,";
1649 clsoptions << "b5paper,";
1651 case PAPER_USEXECUTIVE:
1652 clsoptions << "executivepaper,";
1655 clsoptions << "legalpaper,";
1689 if (sides != tclass.sides()) {
1692 clsoptions << "oneside,";
1695 clsoptions << "twoside,";
1701 if (columns != tclass.columns()) {
1703 clsoptions << "twocolumn,";
1705 clsoptions << "onecolumn,";
1709 && orientation == ORIENTATION_LANDSCAPE)
1710 clsoptions << "landscape,";
1713 clsoptions << "fleqn,";
1715 switch(math_numbering_side) {
1717 clsoptions << "leqno,";
1720 clsoptions << "reqno,";
1721 features.require("amsmath");
1727 // language should be a parameter to \documentclass
1728 if (language->babel() == "hebrew"
1729 && default_language->babel() != "hebrew")
1730 // This seems necessary
1731 features.useLanguage(default_language);
1733 ostringstream language_options;
1734 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1735 bool const use_polyglossia = features.usePolyglossia();
1736 bool const global = lyxrc.language_global_options;
1737 if (features.useBabel() || (use_polyglossia && global)) {
1738 language_options << features.getBabelLanguages();
1739 if (!language->babel().empty()) {
1740 if (!language_options.str().empty())
1741 language_options << ',';
1742 language_options << language->babel();
1744 if (global && !language_options.str().empty())
1745 clsoptions << language_options.str() << ',';
1748 // the predefined options from the layout
1749 if (use_default_options && !tclass.options().empty())
1750 clsoptions << tclass.options() << ',';
1752 // the user-defined options
1753 if (!options.empty()) {
1754 clsoptions << options << ',';
1757 string strOptions(clsoptions.str());
1758 if (!strOptions.empty()) {
1759 strOptions = rtrim(strOptions, ",");
1761 os << '[' << from_utf8(strOptions) << ']';
1764 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1765 // end of \documentclass defs
1767 // if we use fontspec or newtxmath, we have to load the AMS packages here
1768 string const ams = features.loadAMSPackages();
1769 bool const ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1");
1770 bool const use_newtxmath =
1771 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1772 ot1, false, false) == "newtxmath";
1773 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1774 os << from_ascii(ams);
1776 if (useNonTeXFonts) {
1777 // Babel loads fontspec itself
1778 if (!features.isProvided("fontspec") && !features.useBabel())
1779 os << "\\usepackage{fontspec}\n";
1780 if (features.mustProvide("unicode-math")
1781 && features.isAvailable("unicode-math"))
1782 os << "\\usepackage{unicode-math}\n";
1785 // load CJK support package before font selection
1786 // (see autotests/export/latex/CJK/micro-sign_utf8-cjk-libertine.lyx)
1787 if (!useNonTeXFonts && encoding().package() != Encoding::none && inputenc != "utf8x"
1788 && (encoding().package() == Encoding::CJK || features.mustProvide("CJK"))) {
1789 if (inputenc == "utf8-cjk" || inputenc == "utf8")
1790 os << "\\usepackage{CJKutf8}\n";
1792 os << "\\usepackage[encapsulated]{CJK}\n";
1795 // font selection must be done before loading fontenc.sty
1796 // but after babel with non-TeX fonts
1797 string const fonts = loadFonts(features);
1798 if (!fonts.empty() && (!features.useBabel() || !useNonTeXFonts))
1799 os << from_utf8(fonts);
1801 if (fonts_default_family != "default")
1802 os << "\\renewcommand{\\familydefault}{\\"
1803 << from_ascii(fonts_default_family) << "}\n";
1805 // set font encoding
1806 // non-TeX fonts use font encoding TU (set by fontspec)
1807 if (!useNonTeXFonts && !features.isProvided("fontenc")
1808 && main_font_encoding() != "default") {
1809 // get main font encodings
1810 vector<string> fontencs = font_encodings();
1811 // get font encodings of secondary languages
1812 // FIXME: some languages (hebrew, ...) assume a standard font encoding as last
1813 // option (for text in other languages).
1814 features.getFontEncodings(fontencs);
1815 if (!fontencs.empty()) {
1816 os << "\\usepackage["
1817 << from_ascii(getStringFromVector(fontencs))
1822 // Load textcomp and pmboxdraw before (lua)inputenc (#11454)
1823 if (features.mustProvide("textcomp"))
1824 os << "\\usepackage{textcomp}\n";
1825 if (features.mustProvide("pmboxdraw"))
1826 os << "\\usepackage{pmboxdraw}\n";
1828 // handle inputenc etc.
1829 // (In documents containing text in Thai language,
1830 // we must load inputenc after babel, see lib/languages).
1831 if (!contains(features.getBabelPostsettings(), from_ascii("thai.ldf")))
1832 writeEncodingPreamble(os, features);
1835 if (!features.runparams().includeall && !included_children_.empty()) {
1836 os << "\\includeonly{";
1837 list<string>::const_iterator it = included_children_.begin();
1838 list<string>::const_iterator en = included_children_.end();
1840 for (; it != en; ++it) {
1841 string incfile = *it;
1842 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1843 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1845 if (!features.runparams().nice)
1847 // \includeonly doesn't want an extension
1848 incfile = changeExtension(incfile, string());
1849 incfile = support::latex_path(incfile);
1850 if (!incfile.empty()) {
1853 os << from_utf8(incfile);
1860 if (!features.isProvided("geometry")
1861 && (use_geometry || nonstandard_papersize)) {
1862 odocstringstream ods;
1863 if (!getGraphicsDriver("geometry").empty())
1864 ods << getGraphicsDriver("geometry");
1865 if (orientation == ORIENTATION_LANDSCAPE)
1866 ods << ",landscape";
1867 switch (papersize) {
1869 if (!paperwidth.empty())
1870 ods << ",paperwidth="
1871 << from_ascii(paperwidth);
1872 if (!paperheight.empty())
1873 ods << ",paperheight="
1874 << from_ascii(paperheight);
1876 case PAPER_USLETTER:
1877 ods << ",letterpaper";
1880 ods << ",legalpaper";
1882 case PAPER_USEXECUTIVE:
1883 ods << ",executivepaper";
1972 docstring const g_options = trim(ods.str(), ",");
1973 os << "\\usepackage";
1974 if (!g_options.empty())
1975 os << '[' << g_options << ']';
1976 os << "{geometry}\n";
1977 // output this only if use_geometry is true
1979 os << "\\geometry{verbose";
1980 if (!topmargin.empty())
1981 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1982 if (!bottommargin.empty())
1983 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1984 if (!leftmargin.empty())
1985 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1986 if (!rightmargin.empty())
1987 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1988 if (!headheight.empty())
1989 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1990 if (!headsep.empty())
1991 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1992 if (!footskip.empty())
1993 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1994 if (!columnsep.empty())
1995 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1998 } else if (orientation == ORIENTATION_LANDSCAPE
1999 || papersize != PAPER_DEFAULT) {
2000 features.require("papersize");
2003 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
2004 if (pagestyle == "fancy")
2005 os << "\\usepackage{fancyhdr}\n";
2006 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
2009 // only output when the background color is not default
2010 if (isbackgroundcolor == true) {
2011 // only require color here, the background color will be defined
2012 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
2014 features.require("color");
2015 features.require("pagecolor");
2018 // only output when the font color is not default
2019 if (isfontcolor == true) {
2020 // only require color here, the font color will be defined
2021 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
2023 features.require("color");
2024 features.require("fontcolor");
2027 // Only if class has a ToC hierarchy
2028 if (tclass.hasTocLevels()) {
2029 if (secnumdepth != tclass.secnumdepth()) {
2030 os << "\\setcounter{secnumdepth}{"
2034 if (tocdepth != tclass.tocdepth()) {
2035 os << "\\setcounter{tocdepth}{"
2041 if (paragraph_separation) {
2042 // when skip separation
2043 switch (getDefSkip().kind()) {
2044 case VSpace::SMALLSKIP:
2045 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
2047 case VSpace::MEDSKIP:
2048 os << "\\setlength{\\parskip}{\\medskipamount}\n";
2050 case VSpace::BIGSKIP:
2051 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
2053 case VSpace::LENGTH:
2054 os << "\\setlength{\\parskip}{"
2055 << from_utf8(getDefSkip().length().asLatexString())
2058 default: // should never happen // Then delete it.
2059 os << "\\setlength{\\parskip}{\\medskipamount}\n";
2062 os << "\\setlength{\\parindent}{0pt}\n";
2064 // when separation by indentation
2065 // only output something when a width is given
2066 if (!getParIndent().empty()) {
2067 os << "\\setlength{\\parindent}{"
2068 << from_utf8(getParIndent().asLatexString())
2073 if (is_math_indent) {
2074 // when formula indentation
2075 // only output something when it is not the default
2076 if (!getMathIndent().empty()) {
2077 os << "\\setlength{\\mathindent}{"
2078 << from_utf8(getMathIndent().asString())
2083 // Now insert the LyX specific LaTeX commands...
2084 features.resolveAlternatives();
2085 features.expandMultiples();
2088 if (!output_sync_macro.empty())
2089 os << from_utf8(output_sync_macro) +"\n";
2090 else if (features.runparams().flavor == OutputParams::LATEX)
2091 os << "\\usepackage[active]{srcltx}\n";
2092 else if (features.runparams().flavor == OutputParams::PDFLATEX)
2093 os << "\\synctex=-1\n";
2096 // The package options (via \PassOptionsToPackage)
2097 os << from_ascii(features.getPackageOptions());
2099 // due to interferences with babel and hyperref, the color package has to
2100 // be loaded (when it is not already loaded) before babel when hyperref
2101 // is used with the colorlinks option, see
2102 // http://www.lyx.org/trac/ticket/5291
2103 // we decided therefore to load color always before babel, see
2104 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
2105 os << from_ascii(features.getColorOptions());
2107 // If we use hyperref, jurabib, japanese or varioref,
2108 // we have to call babel before
2110 && (features.isRequired("jurabib")
2111 || features.isRequired("hyperref")
2112 || features.isRequired("varioref")
2113 || features.isRequired("japanese"))) {
2114 os << features.getBabelPresettings();
2116 os << from_utf8(babelCall(language_options.str(),
2117 !lyxrc.language_global_options)) + '\n';
2118 os << features.getBabelPostsettings();
2121 // The optional packages;
2122 os << from_ascii(features.getPackages());
2124 // Additional Indices
2125 if (features.isRequired("splitidx")) {
2126 IndicesList::const_iterator iit = indiceslist().begin();
2127 IndicesList::const_iterator iend = indiceslist().end();
2128 for (; iit != iend; ++iit) {
2129 os << "\\newindex{";
2130 os << escape(iit->shortcut());
2136 os << from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
2139 // * Hyperref manual: "Make sure it comes last of your loaded
2140 // packages, to give it a fighting chance of not being over-written,
2141 // since its job is to redefine many LaTeX commands."
2142 // * Email from Heiko Oberdiek: "It is usually better to load babel
2143 // before hyperref. Then hyperref has a chance to detect babel.
2144 // * Has to be loaded before the "LyX specific LaTeX commands" to
2145 // avoid errors with algorithm floats.
2146 // use hyperref explicitly if it is required
2147 if (features.isRequired("hyperref")) {
2148 OutputParams tmp_params = features.runparams();
2149 pdfoptions().writeLaTeX(tmp_params, os,
2150 features.isProvided("hyperref"));
2151 // correctly break URLs with hyperref and dvi/ps output
2152 if (features.runparams().hyperref_driver == "dvips"
2153 && features.isAvailable("breakurl"))
2154 os << "\\usepackage{breakurl}\n";
2155 } else if (features.isRequired("nameref"))
2156 // hyperref loads this automatically
2157 os << "\\usepackage{nameref}\n";
2160 os << "\\usepackage";
2161 if (!lineno_opts.empty())
2162 os << "[" << lineno_opts << "]";
2164 os << "\\linenumbers\n";
2167 // bibtopic needs to be loaded after hyperref.
2168 // the dot provides the aux file naming which LyX can detect.
2169 if (features.mustProvide("bibtopic"))
2170 os << "\\usepackage[dot]{bibtopic}\n";
2172 // Will be surrounded by \makeatletter and \makeatother when not empty
2173 otexstringstream atlyxpreamble;
2175 // Some macros LyX will need
2177 TexString tmppreamble = features.getMacros();
2178 if (!tmppreamble.str.empty())
2179 atlyxpreamble << "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2180 "LyX specific LaTeX commands.\n"
2181 << move(tmppreamble)
2184 // the text class specific preamble
2186 docstring tmppreamble = features.getTClassPreamble();
2187 if (!tmppreamble.empty())
2188 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2189 "Textclass specific LaTeX commands.\n"
2193 // suppress date if selected
2194 // use \@ifundefined because we cannot be sure that every document class
2195 // has a \date command
2197 atlyxpreamble << "\\@ifundefined{date}{}{\\date{}}\n";
2199 /* the user-defined preamble */
2200 if (!containsOnly(preamble, " \n\t")) {
2202 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2203 "User specified LaTeX commands.\n";
2205 // Check if the user preamble contains uncodable glyphs
2206 odocstringstream user_preamble;
2207 docstring uncodable_glyphs;
2208 Encoding const * const enc = features.runparams().encoding;
2210 for (size_t n = 0; n < preamble.size(); ++n) {
2211 char_type c = preamble[n];
2212 if (!enc->encodable(c)) {
2213 docstring const glyph(1, c);
2214 LYXERR0("Uncodable character '"
2216 << "' in user preamble!");
2217 uncodable_glyphs += glyph;
2218 if (features.runparams().dryrun) {
2219 user_preamble << "<" << _("LyX Warning: ")
2220 << _("uncodable character") << " '";
2221 user_preamble.put(c);
2222 user_preamble << "'>";
2225 user_preamble.put(c);
2228 user_preamble << preamble;
2230 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2231 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2232 frontend::Alert::warning(
2233 _("Uncodable character in user preamble"),
2235 _("The user preamble of your document contains glyphs "
2236 "that are unknown in the current document encoding "
2237 "(namely %1$s).\nThese glyphs are omitted "
2238 " from the output, which may result in "
2239 "incomplete output."
2240 "\n\nPlease select an appropriate "
2241 "document encoding\n"
2242 "(such as utf8) or change the "
2243 "preamble code accordingly."),
2246 atlyxpreamble << user_preamble.str() << '\n';
2249 // footmisc must be loaded after setspace
2250 // Load it here to avoid clashes with footmisc loaded in the user
2251 // preamble. For that reason we also pass the options via
2252 // \PassOptionsToPackage in getPreamble() and not here.
2253 if (features.mustProvide("footmisc"))
2254 atlyxpreamble << "\\usepackage{footmisc}\n";
2256 // subfig loads internally the LaTeX package "caption". As
2257 // caption is a very popular package, users will load it in
2258 // the preamble. Therefore we must load subfig behind the
2259 // user-defined preamble and check if the caption package was
2260 // loaded or not. For the case that caption is loaded before
2261 // subfig, there is the subfig option "caption=false". This
2262 // option also works when a koma-script class is used and
2263 // koma's own caption commands are used instead of caption. We
2264 // use \PassOptionsToPackage here because the user could have
2265 // already loaded subfig in the preamble.
2266 if (features.mustProvide("subfig"))
2267 atlyxpreamble << "\\@ifundefined{showcaptionsetup}{}{%\n"
2268 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2269 "\\usepackage{subfig}\n";
2271 // Itemize bullet settings need to be last in case the user
2272 // defines their own bullets that use a package included
2273 // in the user-defined preamble -- ARRae
2274 // Actually it has to be done much later than that
2275 // since some packages like frenchb make modifications
2276 // at \begin{document} time -- JMarc
2277 docstring bullets_def;
2278 for (int i = 0; i < 4; ++i) {
2279 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2280 if (bullets_def.empty())
2281 bullets_def += "\\AtBeginDocument{\n";
2282 bullets_def += " \\def\\labelitemi";
2284 // `i' is one less than the item to modify
2291 bullets_def += "ii";
2297 bullets_def += '{' +
2298 user_defined_bullet(i).getText()
2303 if (!bullets_def.empty())
2304 atlyxpreamble << bullets_def << "}\n\n";
2306 if (!atlyxpreamble.empty())
2307 os << "\n\\makeatletter\n"
2308 << atlyxpreamble.release()
2309 << "\\makeatother\n\n";
2311 // We try to load babel late, in case it interferes with other packages.
2312 // Jurabib, hyperref, varioref, bicaption, menukeys and listings (bug 8995)
2313 // have to be called after babel, though.
2314 if (use_babel && !features.isRequired("jurabib")
2315 && !features.isRequired("hyperref")
2316 && !features.isRequired("varioref")
2317 && !features.isRequired("japanese")) {
2318 os << features.getBabelPresettings();
2320 os << from_utf8(babelCall(language_options.str(),
2321 !lyxrc.language_global_options)) + '\n';
2322 os << features.getBabelPostsettings();
2324 // In documents containing text in Thai language,
2325 // we must load inputenc after babel (see lib/languages).
2326 if (contains(features.getBabelPostsettings(), from_ascii("thai.ldf")))
2327 writeEncodingPreamble(os, features);
2329 // font selection must be done after babel with non-TeX fonts
2330 if (!fonts.empty() && features.useBabel() && useNonTeXFonts)
2331 os << from_utf8(fonts);
2333 if (features.isRequired("bicaption"))
2334 os << "\\usepackage{bicaption}\n";
2335 if (!listings_params.empty()
2336 || features.mustProvide("listings")
2337 || features.mustProvide("minted")) {
2339 os << "\\usepackage{minted}\n";
2341 os << "\\usepackage{listings}\n";
2343 string lst_params = listings_params;
2344 // If minted, do not output the language option (bug 11203)
2345 if (use_minted && contains(lst_params, "language=")) {
2346 vector<string> opts =
2347 getVectorFromString(lst_params, ",", false);
2348 for (size_t i = 0; i < opts.size(); ++i) {
2349 if (prefixIs(opts[i], "language="))
2350 opts.erase(opts.begin() + i--);
2352 lst_params = getStringFromVector(opts, ",");
2354 if (!lst_params.empty()) {
2356 os << "\\setminted{";
2359 // do not test validity because listings_params is
2360 // supposed to be valid
2362 InsetListingsParams(lst_params).separatedParams(true);
2363 os << from_utf8(par);
2367 // xunicode only needs to be loaded if tipa is used
2368 // (the rest is obsoleted by the new TU encoding).
2369 // It needs to be loaded at least after amsmath, amssymb,
2370 // esint and the other packages that provide special glyphs
2371 if (features.mustProvide("tipa") && useNonTeXFonts
2372 && !features.isProvided("xunicode")) {
2373 // The `xunicode` package officially only supports XeTeX,
2374 // but also works with LuaTeX. We work around its XeTeX test.
2375 if (features.runparams().flavor != OutputParams::XETEX) {
2376 os << "% Pretend to xunicode that we are XeTeX\n"
2377 << "\\def\\XeTeXpicfile{}\n";
2379 os << "\\usepackage{xunicode}\n";
2382 // covington must be loaded after beamerarticle
2383 if (features.isRequired("covington"))
2384 os << "\\usepackage{covington}\n";
2386 // Polyglossia must be loaded last ...
2387 if (use_polyglossia) {
2389 os << "\\usepackage{polyglossia}\n";
2390 // set the main language
2391 os << "\\setdefaultlanguage";
2392 if (!language->polyglossiaOpts().empty())
2393 os << "[" << from_ascii(language->polyglossiaOpts()) << "]";
2394 os << "{" << from_ascii(language->polyglossia()) << "}\n";
2395 // now setup the other languages
2396 set<string> const polylangs =
2397 features.getPolyglossiaLanguages();
2398 for (set<string>::const_iterator mit = polylangs.begin();
2399 mit != polylangs.end() ; ++mit) {
2400 // We do not output the options here; they are output in
2401 // the language switch commands. This is safer if multiple
2402 // varieties are used.
2403 if (*mit == language->polyglossia())
2405 os << "\\setotherlanguage";
2406 os << "{" << from_ascii(*mit) << "}\n";
2410 // ... but before biblatex (see #7065)
2411 if ((features.mustProvide("biblatex")
2412 || features.isRequired("biblatex-chicago"))
2413 && !features.isProvided("biblatex-chicago")
2414 && !features.isProvided("biblatex-natbib")
2415 && !features.isProvided("natbib-internal")
2416 && !features.isProvided("natbib")
2417 && !features.isProvided("jurabib")) {
2418 // The biblatex-chicago package has a differing interface
2419 // it uses a wrapper package and loads styles via fixed options
2420 bool const chicago = features.isRequired("biblatex-chicago");
2423 os << "\\usepackage";
2424 if (!biblatex_bibstyle.empty()
2425 && (biblatex_bibstyle == biblatex_citestyle)
2427 opts = "style=" + biblatex_bibstyle;
2429 } else if (!chicago) {
2430 if (!biblatex_bibstyle.empty()) {
2431 opts = "bibstyle=" + biblatex_bibstyle;
2434 if (!biblatex_citestyle.empty()) {
2435 opts += delim + "citestyle=" + biblatex_citestyle;
2439 if (!multibib.empty() && multibib != "child") {
2440 opts += delim + "refsection=" + multibib;
2443 if (bibtexCommand() == "bibtex8"
2444 || prefixIs(bibtexCommand(), "bibtex8 ")) {
2445 opts += delim + "backend=bibtex8";
2447 } else if (bibtexCommand() == "bibtex"
2448 || prefixIs(bibtexCommand(), "bibtex ")) {
2449 opts += delim + "backend=bibtex";
2452 if (!bib_encoding.empty() && encodings.fromLyXName(bib_encoding)) {
2453 opts += delim + "bibencoding="
2454 + encodings.fromLyXName(bib_encoding)->latexName();
2457 if (!biblio_opts.empty())
2458 opts += delim + biblio_opts;
2460 os << "[" << opts << "]";
2462 os << "{biblatex-chicago}\n";
2464 os << "{biblatex}\n";
2468 // Load custom language package here
2469 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2470 if (lang_package == "default")
2471 os << from_utf8(lyxrc.language_custom_package);
2473 os << from_utf8(lang_package);
2477 // Since menukeys uses catoptions, which does some heavy changes on key-value options,
2478 // it is recommended to load menukeys as the last package (even after hyperref)
2479 if (features.isRequired("menukeys"))
2480 os << "\\usepackage{menukeys}\n";
2482 docstring const i18npreamble =
2483 features.getTClassI18nPreamble(use_babel, use_polyglossia,
2485 if (!i18npreamble.empty())
2486 os << i18npreamble + '\n';
2492 void BufferParams::useClassDefaults()
2494 DocumentClass const & tclass = documentClass();
2496 sides = tclass.sides();
2497 columns = tclass.columns();
2498 pagestyle = tclass.pagestyle();
2499 tablestyle = tclass.tablestyle();
2500 use_default_options = true;
2501 // Only if class has a ToC hierarchy
2502 if (tclass.hasTocLevels()) {
2503 secnumdepth = tclass.secnumdepth();
2504 tocdepth = tclass.tocdepth();
2509 bool BufferParams::hasClassDefaults() const
2511 DocumentClass const & tclass = documentClass();
2513 return sides == tclass.sides()
2514 && columns == tclass.columns()
2515 && pagestyle == tclass.pagestyle()
2516 && tablestyle == tclass.tablestyle()
2517 && use_default_options
2518 && secnumdepth == tclass.secnumdepth()
2519 && tocdepth == tclass.tocdepth();
2523 DocumentClass const & BufferParams::documentClass() const
2529 DocumentClassConstPtr BufferParams::documentClassPtr() const
2535 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2537 // evil, but this function is evil
2538 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2539 invalidateConverterCache();
2543 bool BufferParams::setBaseClass(string const & classname, string const & path)
2545 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2546 LayoutFileList & bcl = LayoutFileList::get();
2547 if (!bcl.haveClass(classname)) {
2549 bformat(_("The layout file:\n"
2551 "could not be found. A default textclass with default\n"
2552 "layouts will be used. LyX will not be able to produce\n"
2554 from_utf8(classname));
2555 frontend::Alert::error(_("Document class not found"), s);
2556 bcl.addEmptyClass(classname);
2559 bool const success = bcl[classname].load(path);
2562 bformat(_("Due to some error in it, the layout file:\n"
2564 "could not be loaded. A default textclass with default\n"
2565 "layouts will be used. LyX will not be able to produce\n"
2567 from_utf8(classname));
2568 frontend::Alert::error(_("Could not load class"), s);
2569 bcl.addEmptyClass(classname);
2572 pimpl_->baseClass_ = classname;
2573 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2578 LayoutFile const * BufferParams::baseClass() const
2580 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2581 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2587 LayoutFileIndex const & BufferParams::baseClassID() const
2589 return pimpl_->baseClass_;
2593 void BufferParams::makeDocumentClass(bool const clone)
2598 invalidateConverterCache();
2599 LayoutModuleList mods;
2600 LayoutModuleList::iterator it = layout_modules_.begin();
2601 LayoutModuleList::iterator en = layout_modules_.end();
2602 for (; it != en; ++it)
2603 mods.push_back(*it);
2605 doc_class_ = getDocumentClass(*baseClass(), mods, cite_engine_, clone);
2607 TextClass::ReturnValues success = TextClass::OK;
2608 if (!forced_local_layout_.empty())
2609 success = doc_class_->read(to_utf8(forced_local_layout_),
2611 if (!local_layout_.empty() &&
2612 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2613 success = doc_class_->read(to_utf8(local_layout_), TextClass::MODULE);
2614 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2615 docstring const msg = _("Error reading internal layout information");
2616 frontend::Alert::warning(_("Read Error"), msg);
2621 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2623 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2627 docstring BufferParams::getLocalLayout(bool forced) const
2630 return from_utf8(doc_class_->forcedLayouts());
2632 return local_layout_;
2636 void BufferParams::setLocalLayout(docstring const & layout, bool forced)
2639 forced_local_layout_ = layout;
2641 local_layout_ = layout;
2645 bool BufferParams::addLayoutModule(string const & modName)
2647 LayoutModuleList::const_iterator it = layout_modules_.begin();
2648 LayoutModuleList::const_iterator end = layout_modules_.end();
2649 for (; it != end; ++it)
2652 layout_modules_.push_back(modName);
2657 string BufferParams::bufferFormat() const
2659 return documentClass().outputFormat();
2663 bool BufferParams::isExportable(string const & format, bool need_viewable) const
2665 FormatList const & formats = exportableFormats(need_viewable);
2666 FormatList::const_iterator fit = formats.begin();
2667 FormatList::const_iterator end = formats.end();
2668 for (; fit != end ; ++fit) {
2669 if ((*fit)->name() == format)
2676 FormatList const & BufferParams::exportableFormats(bool only_viewable) const
2678 FormatList & cached = only_viewable ?
2679 pimpl_->viewableFormatList : pimpl_->exportableFormatList;
2680 bool & valid = only_viewable ?
2681 pimpl_->isViewCacheValid : pimpl_->isExportCacheValid;
2685 vector<string> const backs = backends();
2686 set<string> excludes;
2687 if (useNonTeXFonts) {
2688 excludes.insert("latex");
2689 excludes.insert("pdflatex");
2690 } else if (inputenc != "ascii" && inputenc != "utf8"
2691 && inputenc != "utf8x" && inputenc != "utf8-plain")
2692 // XeTeX with TeX fonts requires input encoding ascii or utf8
2693 // (https://www.tug.org/pipermail/xetex/2010-April/016452.html).
2694 excludes.insert("xetex");
2695 FormatList result = theConverters().getReachable(backs[0], only_viewable,
2697 for (vector<string>::const_iterator it = backs.begin() + 1;
2698 it != backs.end(); ++it) {
2699 FormatList r = theConverters().getReachable(*it, only_viewable,
2701 result.insert(result.end(), r.begin(), r.end());
2703 sort(result.begin(), result.end(), Format::formatSorter);
2710 vector<string> BufferParams::backends() const
2713 string const buffmt = bufferFormat();
2715 // FIXME: Don't hardcode format names here, but use a flag
2716 if (buffmt == "latex") {
2717 if (encoding().package() == Encoding::japanese)
2718 v.push_back("platex");
2720 if (!useNonTeXFonts) {
2721 v.push_back("pdflatex");
2722 v.push_back("latex");
2724 if (useNonTeXFonts || inputenc == "ascii" || inputenc == "utf8"
2725 || inputenc == "utf8x" || inputenc == "utf8-plain")
2726 v.push_back("xetex");
2727 v.push_back("luatex");
2728 v.push_back("dviluatex");
2731 string rbuffmt = buffmt;
2732 // If we use an OutputFormat in Japanese docs,
2733 // we need special format in order to get the path
2734 // via pLaTeX (#8823)
2735 if (documentClass().hasOutputFormat()
2736 && encoding().package() == Encoding::japanese)
2738 v.push_back(rbuffmt);
2741 v.push_back("xhtml");
2742 v.push_back("text");
2748 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2750 string const dformat = (format.empty() || format == "default") ?
2751 getDefaultOutputFormat() : format;
2752 DefaultFlavorCache::const_iterator it =
2753 default_flavors_.find(dformat);
2755 if (it != default_flavors_.end())
2758 OutputParams::FLAVOR result = OutputParams::LATEX;
2760 // FIXME It'd be better not to hardcode this, but to do
2761 // something with formats.
2762 if (dformat == "xhtml")
2763 result = OutputParams::HTML;
2764 else if (dformat == "text")
2765 result = OutputParams::TEXT;
2766 else if (dformat == "lyx")
2767 result = OutputParams::LYX;
2768 else if (dformat == "pdflatex")
2769 result = OutputParams::PDFLATEX;
2770 else if (dformat == "xetex")
2771 result = OutputParams::XETEX;
2772 else if (dformat == "luatex")
2773 result = OutputParams::LUATEX;
2774 else if (dformat == "dviluatex")
2775 result = OutputParams::DVILUATEX;
2777 // Try to determine flavor of default output format
2778 vector<string> backs = backends();
2779 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2780 // Get shortest path to format
2781 Graph::EdgePath path;
2782 for (auto const & bvar : backs) {
2783 Graph::EdgePath p = theConverters().getPath(bvar, dformat);
2784 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2789 result = theConverters().getFlavor(path);
2792 // cache this flavor
2793 default_flavors_[dformat] = result;
2798 string BufferParams::getDefaultOutputFormat() const
2800 if (!default_output_format.empty()
2801 && default_output_format != "default")
2802 return default_output_format;
2804 FormatList const & formats = exportableFormats(true);
2805 if (formats.empty())
2807 // return the first we find
2808 return formats.front()->name();
2810 if (encoding().package() == Encoding::japanese)
2811 return lyxrc.default_platex_view_format;
2813 return lyxrc.default_otf_view_format;
2814 return lyxrc.default_view_format;
2817 Font const BufferParams::getFont() const
2819 FontInfo f = documentClass().defaultfont();
2820 if (fonts_default_family == "rmdefault")
2821 f.setFamily(ROMAN_FAMILY);
2822 else if (fonts_default_family == "sfdefault")
2823 f.setFamily(SANS_FAMILY);
2824 else if (fonts_default_family == "ttdefault")
2825 f.setFamily(TYPEWRITER_FAMILY);
2826 return Font(f, language);
2830 InsetQuotesParams::QuoteStyle BufferParams::getQuoteStyle(string const & qs) const
2832 return quotesstyletranslator().find(qs);
2836 bool BufferParams::isLatex() const
2838 return documentClass().outputType() == LATEX;
2842 bool BufferParams::isLiterate() const
2844 return documentClass().outputType() == LITERATE;
2848 bool BufferParams::isDocBook() const
2850 return documentClass().outputType() == DOCBOOK;
2854 void BufferParams::readPreamble(Lexer & lex)
2856 if (lex.getString() != "\\begin_preamble")
2857 lyxerr << "Error (BufferParams::readPreamble):"
2858 "consistency check failed." << endl;
2860 preamble = lex.getLongString(from_ascii("\\end_preamble"));
2864 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2866 string const expected = forced ? "\\begin_forced_local_layout" :
2867 "\\begin_local_layout";
2868 if (lex.getString() != expected)
2869 lyxerr << "Error (BufferParams::readLocalLayout):"
2870 "consistency check failed." << endl;
2873 forced_local_layout_ =
2874 lex.getLongString(from_ascii("\\end_forced_local_layout"));
2876 local_layout_ = lex.getLongString(from_ascii("\\end_local_layout"));
2880 bool BufferParams::setLanguage(string const & lang)
2882 Language const *new_language = languages.getLanguage(lang);
2883 if (!new_language) {
2884 // Language lang was not found
2887 language = new_language;
2892 void BufferParams::readLanguage(Lexer & lex)
2894 if (!lex.next()) return;
2896 string const tmptok = lex.getString();
2898 // check if tmptok is part of tex_babel in tex-defs.h
2899 if (!setLanguage(tmptok)) {
2900 // Language tmptok was not found
2901 language = default_language;
2902 lyxerr << "Warning: Setting language `"
2903 << tmptok << "' to `" << language->lang()
2909 void BufferParams::readGraphicsDriver(Lexer & lex)
2914 string const tmptok = lex.getString();
2915 // check if tmptok is part of tex_graphics in tex_defs.h
2918 string const test = tex_graphics[n++];
2920 if (test == tmptok) {
2921 graphics_driver = tmptok;
2926 "Warning: graphics driver `$$Token' not recognized!\n"
2927 " Setting graphics driver to `default'.\n");
2928 graphics_driver = "default";
2935 void BufferParams::readBullets(Lexer & lex)
2940 int const index = lex.getInteger();
2942 int temp_int = lex.getInteger();
2943 user_defined_bullet(index).setFont(temp_int);
2944 temp_bullet(index).setFont(temp_int);
2946 user_defined_bullet(index).setCharacter(temp_int);
2947 temp_bullet(index).setCharacter(temp_int);
2949 user_defined_bullet(index).setSize(temp_int);
2950 temp_bullet(index).setSize(temp_int);
2954 void BufferParams::readBulletsLaTeX(Lexer & lex)
2956 // The bullet class should be able to read this.
2959 int const index = lex.getInteger();
2961 docstring const temp_str = lex.getDocString();
2963 user_defined_bullet(index).setText(temp_str);
2964 temp_bullet(index).setText(temp_str);
2968 void BufferParams::readModules(Lexer & lex)
2970 if (!lex.eatLine()) {
2971 lyxerr << "Error (BufferParams::readModules):"
2972 "Unexpected end of input." << endl;
2976 string mod = lex.getString();
2977 if (mod == "\\end_modules")
2979 addLayoutModule(mod);
2985 void BufferParams::readRemovedModules(Lexer & lex)
2987 if (!lex.eatLine()) {
2988 lyxerr << "Error (BufferParams::readRemovedModules):"
2989 "Unexpected end of input." << endl;
2993 string mod = lex.getString();
2994 if (mod == "\\end_removed_modules")
2996 removed_modules_.push_back(mod);
2999 // now we want to remove any removed modules that were previously
3000 // added. normally, that will be because default modules were added in
3001 // setBaseClass(), which gets called when \textclass is read at the
3002 // start of the read.
3003 list<string>::const_iterator rit = removed_modules_.begin();
3004 list<string>::const_iterator const ren = removed_modules_.end();
3005 for (; rit != ren; ++rit) {
3006 LayoutModuleList::iterator const mit = layout_modules_.begin();
3007 LayoutModuleList::iterator const men = layout_modules_.end();
3008 LayoutModuleList::iterator found = find(mit, men, *rit);
3011 layout_modules_.erase(found);
3016 void BufferParams::readIncludeonly(Lexer & lex)
3018 if (!lex.eatLine()) {
3019 lyxerr << "Error (BufferParams::readIncludeonly):"
3020 "Unexpected end of input." << endl;
3024 string child = lex.getString();
3025 if (child == "\\end_includeonly")
3027 included_children_.push_back(child);
3033 string BufferParams::paperSizeName(PapersizePurpose purpose) const
3035 switch (papersize) {
3037 // could be anything, so don't guess
3039 case PAPER_CUSTOM: {
3040 if (purpose == XDVI && !paperwidth.empty() &&
3041 !paperheight.empty()) {
3042 // heightxwidth<unit>
3043 string first = paperwidth;
3044 string second = paperheight;
3045 if (orientation == ORIENTATION_LANDSCAPE)
3048 return first.erase(first.length() - 2)
3054 // dvips and dvipdfm do not know this
3055 if (purpose == DVIPS || purpose == DVIPDFM)
3059 if (purpose == DVIPS || purpose == DVIPDFM)
3063 if (purpose == DVIPS || purpose == DVIPDFM)
3073 if (purpose == DVIPS || purpose == DVIPDFM)
3077 if (purpose == DVIPS || purpose == DVIPDFM)
3081 if (purpose == DVIPS || purpose == DVIPDFM)
3085 if (purpose == DVIPS || purpose == DVIPDFM)
3089 if (purpose == DVIPS || purpose == DVIPDFM)
3093 // dvipdfm does not know this
3094 if (purpose == DVIPDFM)
3098 if (purpose == DVIPDFM)
3102 if (purpose == DVIPS || purpose == DVIPDFM)
3106 if (purpose == DVIPS || purpose == DVIPDFM)
3110 if (purpose == DVIPS || purpose == DVIPDFM)
3114 if (purpose == DVIPS || purpose == DVIPDFM)
3118 if (purpose == DVIPS || purpose == DVIPDFM)
3122 if (purpose == DVIPS || purpose == DVIPDFM)
3126 if (purpose == DVIPS || purpose == DVIPDFM)
3130 if (purpose == DVIPS || purpose == DVIPDFM)
3134 if (purpose == DVIPS || purpose == DVIPDFM)
3138 if (purpose == DVIPS || purpose == DVIPDFM)
3142 if (purpose == DVIPS || purpose == DVIPDFM)
3146 if (purpose == DVIPS || purpose == DVIPDFM)
3150 if (purpose == DVIPS || purpose == DVIPDFM)
3154 if (purpose == DVIPS || purpose == DVIPDFM)
3158 if (purpose == DVIPS || purpose == DVIPDFM)
3161 case PAPER_USEXECUTIVE:
3162 // dvipdfm does not know this
3163 if (purpose == DVIPDFM)
3168 case PAPER_USLETTER:
3170 if (purpose == XDVI)
3177 string const BufferParams::dvips_options() const
3181 // If the class loads the geometry package, we do not know which
3182 // paper size is used, since we do not set it (bug 7013).
3183 // Therefore we must not specify any argument here.
3184 // dvips gets the correct paper size via DVI specials in this case
3185 // (if the class uses the geometry package correctly).
3186 if (documentClass().provides("geometry"))
3190 && papersize == PAPER_CUSTOM
3191 && !lyxrc.print_paper_dimension_flag.empty()
3192 && !paperwidth.empty()
3193 && !paperheight.empty()) {
3194 // using a custom papersize
3195 result = lyxrc.print_paper_dimension_flag;
3196 result += ' ' + paperwidth;
3197 result += ',' + paperheight;
3199 string const paper_option = paperSizeName(DVIPS);
3200 if (!paper_option.empty() && (paper_option != "letter" ||
3201 orientation != ORIENTATION_LANDSCAPE)) {
3202 // dvips won't accept -t letter -t landscape.
3203 // In all other cases, include the paper size
3205 result = lyxrc.print_paper_flag;
3206 result += ' ' + paper_option;
3209 if (orientation == ORIENTATION_LANDSCAPE &&
3210 papersize != PAPER_CUSTOM)
3211 result += ' ' + lyxrc.print_landscape_flag;
3216 string const BufferParams::main_font_encoding() const
3218 if (font_encodings().empty()) {
3219 if (ascii_lowercase(language->fontenc(*this)) == "none")
3223 return font_encodings().back();
3227 vector<string> const BufferParams::font_encodings() const
3229 string doc_fontenc = (fontenc == "auto") ? string() : fontenc;
3231 vector<string> fontencs;
3233 // "default" means "no explicit font encoding"
3234 if (doc_fontenc != "default") {
3235 if (!doc_fontenc.empty())
3236 // If we have a custom setting, we use only that!
3237 return getVectorFromString(doc_fontenc);
3238 if (!language->fontenc(*this).empty()
3239 && ascii_lowercase(language->fontenc(*this)) != "none") {
3240 vector<string> fencs = getVectorFromString(language->fontenc(*this));
3241 for (auto & fe : fencs) {
3242 if (find(fontencs.begin(), fontencs.end(), fe) == fontencs.end())
3243 fontencs.push_back(fe);
3252 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
3254 // suppress the babel call if there is no BabelName defined
3255 // for the document language in the lib/languages file and if no
3256 // other languages are used (lang_opts is then empty)
3257 if (lang_opts.empty())
3259 // The prefs may require the languages to
3260 // be submitted to babel itself (not the class).
3262 return "\\usepackage[" + lang_opts + "]{babel}";
3263 return "\\usepackage{babel}";
3267 docstring BufferParams::getGraphicsDriver(string const & package) const
3271 if (package == "geometry") {
3272 if (graphics_driver == "dvips"
3273 || graphics_driver == "dvipdfm"
3274 || graphics_driver == "pdftex"
3275 || graphics_driver == "vtex")
3276 result = from_ascii(graphics_driver);
3277 else if (graphics_driver == "dvipdfmx")
3278 result = from_ascii("dvipdfm");
3285 void BufferParams::writeEncodingPreamble(otexstream & os,
3286 LaTeXFeatures & features) const
3288 // With no-TeX fonts we use utf8-plain without encoding package.
3292 if (inputenc == "auto-legacy") {
3293 string const doc_encoding =
3294 language->encoding()->latexName();
3295 Encoding::Package const package =
3296 language->encoding()->package();
3298 // Create list of inputenc options:
3299 set<string> encoding_set;
3300 // luainputenc fails with more than one encoding
3301 if (features.runparams().flavor != OutputParams::LUATEX
3302 && features.runparams().flavor != OutputParams::DVILUATEX)
3303 // list all input encodings used in the document
3304 encoding_set = features.getEncodingSet(doc_encoding);
3306 // The "japanese" babel-language requires the pLaTeX engine
3307 // which conflicts with "inputenc".
3308 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
3309 if ((!encoding_set.empty() || package == Encoding::inputenc)
3310 && !features.isRequired("japanese")
3311 && !features.isProvided("inputenc")) {
3312 os << "\\usepackage[";
3313 set<string>::const_iterator it = encoding_set.begin();
3314 set<string>::const_iterator const end = encoding_set.end();
3316 os << from_ascii(*it);
3319 for (; it != end; ++it)
3320 os << ',' << from_ascii(*it);
3321 if (package == Encoding::inputenc) {
3322 if (!encoding_set.empty())
3324 os << from_ascii(doc_encoding);
3326 if (features.runparams().flavor == OutputParams::LUATEX
3327 || features.runparams().flavor == OutputParams::DVILUATEX)
3328 os << "]{luainputenc}\n";
3330 os << "]{inputenc}\n";
3332 } else if (inputenc != "auto-legacy-plain") {
3333 switch (encoding().package()) {
3334 case Encoding::none:
3336 case Encoding::japanese:
3337 if (encoding().iconvName() != "UTF-8"
3338 && !features.runparams().isFullUnicode())
3339 // don't default to [utf8]{inputenc} with TeXLive >= 18
3340 os << "\\ifdefined\\UseRawInputEncoding\n"
3341 << " \\UseRawInputEncoding\\fi\n";
3343 case Encoding::inputenc:
3344 // do not load inputenc if japanese is used
3345 // or if the class provides inputenc
3346 if (features.isRequired("japanese")
3347 || features.isProvided("inputenc"))
3349 if (features.runparams().flavor == OutputParams::XETEX)
3350 os << xetex_pre_inputenc;
3351 os << "\\usepackage[" << from_ascii(encoding().latexName());
3352 if (features.runparams().flavor == OutputParams::LUATEX
3353 || features.runparams().flavor == OutputParams::DVILUATEX)
3354 os << "]{luainputenc}\n";
3356 os << "]{inputenc}\n";
3357 if (features.runparams().flavor == OutputParams::XETEX)
3358 os << xetex_post_inputenc;
3362 if (inputenc == "auto-legacy-plain" || features.isRequired("japanese")) {
3363 // don't default to [utf8]{inputenc} with TeXLive >= 18
3364 os << "\\ifdefined\\UseRawInputEncoding\n";
3365 os << " \\UseRawInputEncoding\\fi\n";
3370 string const BufferParams::parseFontName(string const & name) const
3372 string mangled = name;
3373 size_t const idx = mangled.find('[');
3374 if (idx == string::npos || idx == 0)
3377 return mangled.substr(0, idx - 1);
3381 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3383 if (fontsRoman() == "default" && fontsSans() == "default"
3384 && fontsTypewriter() == "default"
3385 && (fontsMath() == "default" || fontsMath() == "auto"))
3391 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3392 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3393 * Mapping=tex-text option assures TeX ligatures (such as "--")
3394 * are resolved. Note that tt does not use these ligatures.
3396 * -- add more GUI options?
3397 * -- add more fonts (fonts for other scripts)
3398 * -- if there's a way to find out if a font really supports
3399 * OldStyle, enable/disable the widget accordingly.
3401 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3402 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3403 // However, until v.2 (2010/07/11) fontspec only knew
3404 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3405 // was introduced for both XeTeX and LuaTeX (LuaTeX
3406 // didn't understand "Mapping=tex-text", while XeTeX
3407 // understood both. With most recent versions, both
3408 // variants are understood by both engines. However,
3409 // we want to provide support for at least TeXLive 2009
3410 // (for XeTeX; LuaTeX is only supported as of v.2)
3411 // Babel has its own higher-level interface on top of
3412 // fontspec that is to be used.
3413 bool const babel = features.useBabel();
3414 string const texmapping =
3415 (features.runparams().flavor == OutputParams::XETEX) ?
3416 "Mapping=tex-text" : "Ligatures=TeX";
3417 if (fontsRoman() != "default") {
3419 os << "\\babelfont{rm}[";
3421 os << "\\setmainfont[";
3422 if (!font_roman_opts.empty())
3423 os << font_roman_opts << ',';
3425 if (fonts_old_figures)
3426 os << ",Numbers=OldStyle";
3427 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3429 if (fontsSans() != "default") {
3430 string const sans = parseFontName(fontsSans());
3431 if (fontsSansScale() != 100) {
3433 os << "\\babelfont{sf}";
3435 os << "\\setsansfont";
3437 << float(fontsSansScale()) / 100 << ',';
3438 if (!font_sans_opts.empty())
3439 os << font_sans_opts << ',';
3440 os << texmapping << "]{"
3444 os << "\\babelfont{sf}[";
3446 os << "\\setsansfont[";
3447 if (!font_sans_opts.empty())
3448 os << font_sans_opts << ',';
3449 os << texmapping << "]{"
3453 if (fontsTypewriter() != "default") {
3454 string const mono = parseFontName(fontsTypewriter());
3455 if (fontsTypewriterScale() != 100) {
3457 os << "\\babelfont{tt}";
3459 os << "\\setmonofont";
3461 << float(fontsTypewriterScale()) / 100;
3462 if (!font_typewriter_opts.empty())
3463 os << ',' << font_typewriter_opts;
3468 os << "\\babelfont{tt}";
3470 os << "\\setmonofont";
3471 if (!font_typewriter_opts.empty())
3472 os << '[' << font_typewriter_opts << ']';
3473 os << '{' << mono << "}\n";
3480 bool const ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1");
3481 bool const dryrun = features.runparams().dryrun;
3482 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3483 bool const nomath = (fontsMath() == "default");
3486 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3487 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3488 nomath, font_roman_opts);
3491 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3492 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3493 nomath, font_roman_opts, fontsSansScale());
3495 // MONOSPACED/TYPEWRITER
3496 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3497 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3498 nomath, font_roman_opts, fontsTypewriterScale());
3501 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3502 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3509 Encoding const & BufferParams::encoding() const
3511 // Main encoding for LaTeX output.
3513 return *(encodings.fromLyXName("utf8-plain"));
3514 if (inputenc == "auto-legacy" || inputenc == "auto-legacy-plain")
3515 return *language->encoding();
3516 if (inputenc == "utf8" && language->lang() == "japanese")
3517 return *(encodings.fromLyXName("utf8-platex"));
3518 Encoding const * const enc = encodings.fromLyXName(inputenc);
3521 LYXERR0("Unknown inputenc value `" << inputenc
3522 << "'. Using `auto' instead.");
3523 return *language->encoding();
3527 string const & BufferParams::defaultBiblioStyle() const
3529 if (!biblio_style.empty())
3530 return biblio_style;
3532 map<string, string> const & bs = documentClass().defaultBiblioStyle();
3533 auto cit = bs.find(theCiteEnginesList.getTypeAsString(citeEngineType()));
3534 if (cit != bs.end())
3537 return empty_string();
3541 bool const & BufferParams::fullAuthorList() const
3543 return documentClass().fullAuthorList();
3547 string BufferParams::getCiteAlias(string const & s) const
3549 vector<string> commands =
3550 documentClass().citeCommands(citeEngineType());
3551 // If it is a real command, don't treat it as an alias
3552 if (find(commands.begin(), commands.end(), s) != commands.end())
3554 map<string,string> aliases = documentClass().citeCommandAliases();
3555 if (aliases.find(s) != aliases.end())
3561 vector<string> BufferParams::citeCommands() const
3563 static CitationStyle const default_style;
3564 vector<string> commands =
3565 documentClass().citeCommands(citeEngineType());
3566 if (commands.empty())
3567 commands.push_back(default_style.name);
3572 vector<CitationStyle> BufferParams::citeStyles() const
3574 static CitationStyle const default_style;
3575 vector<CitationStyle> styles =
3576 documentClass().citeStyles(citeEngineType());
3578 styles.push_back(default_style);
3583 string const BufferParams::bibtexCommand() const
3585 // Return document-specific setting if available
3586 if (bibtex_command != "default")
3587 return bibtex_command;
3589 // If we have "default" in document settings, consult the prefs
3590 // 1. Japanese (uses a specific processor)
3591 if (encoding().package() == Encoding::japanese) {
3592 if (lyxrc.jbibtex_command != "automatic")
3593 // Return the specified program, if "automatic" is not set
3594 return lyxrc.jbibtex_command;
3595 else if (!useBiblatex()) {
3596 // With classic BibTeX, return pbibtex, jbibtex, bibtex
3597 if (lyxrc.jbibtex_alternatives.find("pbibtex") != lyxrc.jbibtex_alternatives.end())
3599 if (lyxrc.jbibtex_alternatives.find("jbibtex") != lyxrc.jbibtex_alternatives.end())
3604 // 2. All other languages
3605 else if (lyxrc.bibtex_command != "automatic")
3606 // Return the specified program, if "automatic" is not set
3607 return lyxrc.bibtex_command;
3609 // 3. Automatic: find the most suitable for the current cite framework
3610 if (useBiblatex()) {
3611 // For Biblatex, we prefer biber (also for Japanese)
3612 // and fall back to bibtex8 and, as last resort, bibtex
3613 if (lyxrc.bibtex_alternatives.find("biber") != lyxrc.bibtex_alternatives.end())
3615 else if (lyxrc.bibtex_alternatives.find("bibtex8") != lyxrc.bibtex_alternatives.end())
3622 bool BufferParams::useBiblatex() const
3624 return theCiteEnginesList[citeEngine()]->getCiteFramework() == "biblatex";
3628 void BufferParams::invalidateConverterCache() const
3630 pimpl_->isExportCacheValid = false;
3631 pimpl_->isViewCacheValid = false;
3635 // We shouldn't need to reset the params here, since anything
3636 // we need will be recopied.
3637 void BufferParams::copyForAdvFR(const BufferParams & bp)
3639 string const & lang = bp.language->lang();
3641 layout_modules_ = bp.layout_modules_;
3642 string const & doc_class = bp.documentClass().name();
3643 setBaseClass(doc_class);
3647 void BufferParams::setBibFileEncoding(string const & file, string const & enc)
3649 bib_encodings[file] = enc;
3653 string const BufferParams::bibFileEncoding(string const & file) const
3655 if (bib_encodings.find(file) == bib_encodings.end())
3657 return bib_encodings.find(file)->second;