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"
32 #include "IndicesList.h"
34 #include "LaTeXFeatures.h"
35 #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",
111 // Paragraph separation
112 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
115 ParSepTranslator const init_parseptranslator()
117 ParSepTranslator translator
118 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
119 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
124 ParSepTranslator const & parseptranslator()
126 static ParSepTranslator const translator =
127 init_parseptranslator();
133 typedef Translator<string, InsetQuotesParams::QuoteStyle> QuotesStyleTranslator;
136 QuotesStyleTranslator const init_quotesstyletranslator()
138 QuotesStyleTranslator translator
139 (string_quotes_style[0], InsetQuotesParams::EnglishQuotes);
140 translator.addPair(string_quotes_style[1], InsetQuotesParams::SwedishQuotes);
141 translator.addPair(string_quotes_style[2], InsetQuotesParams::GermanQuotes);
142 translator.addPair(string_quotes_style[3], InsetQuotesParams::PolishQuotes);
143 translator.addPair(string_quotes_style[4], InsetQuotesParams::SwissQuotes);
144 translator.addPair(string_quotes_style[5], InsetQuotesParams::DanishQuotes);
145 translator.addPair(string_quotes_style[6], InsetQuotesParams::PlainQuotes);
146 translator.addPair(string_quotes_style[7], InsetQuotesParams::BritishQuotes);
147 translator.addPair(string_quotes_style[8], InsetQuotesParams::SwedishGQuotes);
148 translator.addPair(string_quotes_style[9], InsetQuotesParams::FrenchQuotes);
149 translator.addPair(string_quotes_style[10], InsetQuotesParams::FrenchINQuotes);
150 translator.addPair(string_quotes_style[11], InsetQuotesParams::RussianQuotes);
151 translator.addPair(string_quotes_style[12], InsetQuotesParams::CJKQuotes);
152 translator.addPair(string_quotes_style[13], InsetQuotesParams::CJKAngleQuotes);
157 QuotesStyleTranslator const & quotesstyletranslator()
159 static QuotesStyleTranslator const translator =
160 init_quotesstyletranslator();
166 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
169 static PaperSizeTranslator initPaperSizeTranslator()
171 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
172 translator.addPair(string_papersize[1], PAPER_CUSTOM);
173 translator.addPair(string_papersize[2], PAPER_USLETTER);
174 translator.addPair(string_papersize[3], PAPER_USLEGAL);
175 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
176 translator.addPair(string_papersize[5], PAPER_A0);
177 translator.addPair(string_papersize[6], PAPER_A1);
178 translator.addPair(string_papersize[7], PAPER_A2);
179 translator.addPair(string_papersize[8], PAPER_A3);
180 translator.addPair(string_papersize[9], PAPER_A4);
181 translator.addPair(string_papersize[10], PAPER_A5);
182 translator.addPair(string_papersize[11], PAPER_A6);
183 translator.addPair(string_papersize[12], PAPER_B0);
184 translator.addPair(string_papersize[13], PAPER_B1);
185 translator.addPair(string_papersize[14], PAPER_B2);
186 translator.addPair(string_papersize[15], PAPER_B3);
187 translator.addPair(string_papersize[16], PAPER_B4);
188 translator.addPair(string_papersize[17], PAPER_B5);
189 translator.addPair(string_papersize[18], PAPER_B6);
190 translator.addPair(string_papersize[19], PAPER_C0);
191 translator.addPair(string_papersize[20], PAPER_C1);
192 translator.addPair(string_papersize[21], PAPER_C2);
193 translator.addPair(string_papersize[22], PAPER_C3);
194 translator.addPair(string_papersize[23], PAPER_C4);
195 translator.addPair(string_papersize[24], PAPER_C5);
196 translator.addPair(string_papersize[25], PAPER_C6);
197 translator.addPair(string_papersize[26], PAPER_JISB0);
198 translator.addPair(string_papersize[27], PAPER_JISB1);
199 translator.addPair(string_papersize[28], PAPER_JISB2);
200 translator.addPair(string_papersize[29], PAPER_JISB3);
201 translator.addPair(string_papersize[30], PAPER_JISB4);
202 translator.addPair(string_papersize[31], PAPER_JISB5);
203 translator.addPair(string_papersize[32], PAPER_JISB6);
208 PaperSizeTranslator const & papersizetranslator()
210 static PaperSizeTranslator const translator =
211 initPaperSizeTranslator();
217 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
220 PaperOrientationTranslator const init_paperorientationtranslator()
222 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
223 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
228 PaperOrientationTranslator const & paperorientationtranslator()
230 static PaperOrientationTranslator const translator =
231 init_paperorientationtranslator();
237 typedef Translator<int, PageSides> SidesTranslator;
240 SidesTranslator const init_sidestranslator()
242 SidesTranslator translator(1, OneSide);
243 translator.addPair(2, TwoSides);
248 SidesTranslator const & sidestranslator()
250 static SidesTranslator const translator = init_sidestranslator();
256 typedef Translator<int, BufferParams::Package> PackageTranslator;
259 PackageTranslator const init_packagetranslator()
261 PackageTranslator translator(0, BufferParams::package_off);
262 translator.addPair(1, BufferParams::package_auto);
263 translator.addPair(2, BufferParams::package_on);
268 PackageTranslator const & packagetranslator()
270 static PackageTranslator const translator =
271 init_packagetranslator();
277 typedef Translator<string, Spacing::Space> SpaceTranslator;
280 SpaceTranslator const init_spacetranslator()
282 SpaceTranslator translator("default", Spacing::Default);
283 translator.addPair("single", Spacing::Single);
284 translator.addPair("onehalf", Spacing::Onehalf);
285 translator.addPair("double", Spacing::Double);
286 translator.addPair("other", Spacing::Other);
291 SpaceTranslator const & spacetranslator()
293 static SpaceTranslator const translator = init_spacetranslator();
298 bool inSystemDir(FileName const & document_dir, string & system_dir)
300 // A document is assumed to be in a system LyX directory (not
301 // necessarily the system directory of the running instance)
302 // if both "configure.py" and "chkconfig.ltx" are found in
303 // either document_dir/../ or document_dir/../../.
304 // If true, the system directory path is returned in system_dir
305 // with a trailing path separator.
307 string const msg = "Checking whether document is in a system dir...";
309 string dir = document_dir.absFileName();
311 for (int i = 0; i < 2; ++i) {
312 dir = addPath(dir, "..");
313 if (!fileSearch(dir, "configure.py").empty() &&
314 !fileSearch(dir, "chkconfig.ltx").empty()) {
315 LYXERR(Debug::FILES, msg << " yes");
316 system_dir = addPath(FileName(dir).realPath(), "");
321 LYXERR(Debug::FILES, msg << " no");
322 system_dir = string();
329 class BufferParams::Impl
334 AuthorList authorlist;
335 BranchList branchlist;
336 Bullet temp_bullets[4];
337 Bullet user_defined_bullets[4];
338 IndicesList indiceslist;
340 /** This is the amount of space used for paragraph_separation "skip",
341 * and for detached paragraphs in "indented" documents.
345 PDFOptions pdfoptions;
346 LayoutFileIndex baseClass_;
347 FormatList exportableFormatList;
348 FormatList viewableFormatList;
349 bool isViewCacheValid;
350 bool isExportCacheValid;
354 BufferParams::Impl::Impl()
355 : defskip(VSpace::MEDSKIP), baseClass_(string("")),
356 isViewCacheValid(false), isExportCacheValid(false)
358 // set initial author
360 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
365 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
368 return new BufferParams::Impl(*ptr);
372 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
378 BufferParams::BufferParams()
381 setBaseClass(defaultBaseclass());
382 cite_engine_.push_back("basic");
383 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
385 paragraph_separation = ParagraphIndentSeparation;
386 quotes_style = InsetQuotesParams::EnglishQuotes;
387 dynamic_quotes = false;
388 fontsize = "default";
391 papersize = PAPER_DEFAULT;
392 orientation = ORIENTATION_PORTRAIT;
393 use_geometry = false;
394 biblio_style = "plain";
395 use_bibtopic = false;
398 save_transient_properties = true;
399 track_changes = false;
400 output_changes = false;
401 use_default_options = true;
402 maintain_unincluded_children = false;
405 language = default_language;
407 fonts_roman[0] = "default";
408 fonts_roman[1] = "default";
409 fonts_sans[0] = "default";
410 fonts_sans[1] = "default";
411 fonts_typewriter[0] = "default";
412 fonts_typewriter[1] = "default";
413 fonts_math[0] = "auto";
414 fonts_math[1] = "auto";
415 fonts_default_family = "default";
416 useNonTeXFonts = false;
417 use_microtype = false;
418 fonts_expert_sc = false;
419 fonts_old_figures = false;
420 fonts_sans_scale[0] = 100;
421 fonts_sans_scale[1] = 100;
422 fonts_typewriter_scale[0] = 100;
423 fonts_typewriter_scale[1] = 100;
425 lang_package = "default";
426 graphics_driver = "default";
427 default_output_format = "default";
428 bibtex_command = "default";
429 index_command = "default";
432 listings_params = string();
433 pagestyle = "default";
434 suppress_date = false;
435 justification = true;
436 // no color is the default (white)
437 backgroundcolor = lyx::rgbFromHexName("#ffffff");
438 isbackgroundcolor = false;
439 // no color is the default (black)
440 fontcolor = lyx::rgbFromHexName("#000000");
442 // light gray is the default font color for greyed-out notes
443 notefontcolor = lyx::rgbFromHexName("#cccccc");
444 boxbgcolor = lyx::rgbFromHexName("#ff0000");
445 compressed = lyxrc.save_compressed;
446 for (int iter = 0; iter < 4; ++iter) {
447 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
448 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
451 indiceslist().addDefault(B_("Index"));
452 html_be_strict = false;
453 html_math_output = MathML;
454 html_math_img_scale = 1.0;
455 html_css_as_file = false;
456 display_pixel_ratio = 1.0;
461 // map current author
462 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
466 docstring BufferParams::B_(string const & l10n) const
468 LASSERT(language, return from_utf8(l10n));
469 return getMessages(language->code()).get(l10n);
473 BufferParams::Package BufferParams::use_package(std::string const & p) const
475 PackageMap::const_iterator it = use_packages.find(p);
476 if (it == use_packages.end())
482 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
488 map<string, string> const & BufferParams::auto_packages()
490 static map<string, string> packages;
491 if (packages.empty()) {
492 // We could have a race condition here that two threads
493 // discover an empty map at the same time and want to fill
494 // it, but that is no problem, since the same contents is
495 // filled in twice then. Having the locker inside the
496 // packages.empty() condition has the advantage that we
497 // don't need the mutex overhead for simple reading.
499 Mutex::Locker locker(&mutex);
500 // adding a package here implies a file format change!
501 packages["amsmath"] =
502 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
503 packages["amssymb"] =
504 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
506 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
508 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
509 packages["mathdots"] =
510 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
511 packages["mathtools"] =
512 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
514 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
515 packages["stackrel"] =
516 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
517 packages["stmaryrd"] =
518 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");
519 packages["undertilde"] =
520 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
526 bool BufferParams::useBibtopic() const
530 return (use_bibtopic || (!multibib.empty() && multibib != "child"));
534 AuthorList & BufferParams::authors()
536 return pimpl_->authorlist;
540 AuthorList const & BufferParams::authors() const
542 return pimpl_->authorlist;
546 void BufferParams::addAuthor(Author a)
548 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
552 BranchList & BufferParams::branchlist()
554 return pimpl_->branchlist;
558 BranchList const & BufferParams::branchlist() const
560 return pimpl_->branchlist;
564 IndicesList & BufferParams::indiceslist()
566 return pimpl_->indiceslist;
570 IndicesList const & BufferParams::indiceslist() const
572 return pimpl_->indiceslist;
576 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
578 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
579 return pimpl_->temp_bullets[index];
583 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
585 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
586 return pimpl_->temp_bullets[index];
590 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
592 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
593 return pimpl_->user_defined_bullets[index];
597 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
599 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
600 return pimpl_->user_defined_bullets[index];
604 Spacing & BufferParams::spacing()
606 return pimpl_->spacing;
610 Spacing const & BufferParams::spacing() const
612 return pimpl_->spacing;
616 PDFOptions & BufferParams::pdfoptions()
618 return pimpl_->pdfoptions;
622 PDFOptions const & BufferParams::pdfoptions() const
624 return pimpl_->pdfoptions;
628 HSpace const & BufferParams::getIndentation() const
630 return pimpl_->indentation;
634 void BufferParams::setIndentation(HSpace const & indent)
636 pimpl_->indentation = indent;
640 VSpace const & BufferParams::getDefSkip() const
642 return pimpl_->defskip;
646 void BufferParams::setDefSkip(VSpace const & vs)
648 // DEFSKIP will cause an infinite loop
649 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
650 pimpl_->defskip = vs;
654 string BufferParams::readToken(Lexer & lex, string const & token,
655 FileName const & filepath)
659 if (token == "\\textclass") {
661 string const classname = lex.getString();
662 // if there exists a local layout file, ignore the system one
663 // NOTE: in this case, the textclass (.cls file) is assumed to
666 LayoutFileList & bcl = LayoutFileList::get();
667 if (!filepath.empty()) {
668 // If classname is an absolute path, the document is
669 // using a local layout file which could not be accessed
670 // by a relative path. In this case the path is correct
671 // even if the document was moved to a different
672 // location. However, we will have a problem if the
673 // document was generated on a different platform.
674 bool isabsolute = FileName::isAbsolute(classname);
675 string const classpath = onlyPath(classname);
676 string const path = isabsolute ? classpath
677 : FileName(addPath(filepath.absFileName(),
678 classpath)).realPath();
679 string const oldpath = isabsolute ? string()
680 : FileName(addPath(origin, classpath)).realPath();
681 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
683 // that returns non-empty if a "local" layout file is found.
685 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
686 from_utf8(filepath.absFileName())));
689 setBaseClass(onlyFileName(tcp));
691 setBaseClass(onlyFileName(classname));
692 // We assume that a tex class exists for local or unknown
693 // layouts so this warning, will only be given for system layouts.
694 if (!baseClass()->isTeXClassAvailable()) {
695 docstring const desc =
696 translateIfPossible(from_utf8(baseClass()->description()));
697 docstring const prereqs =
698 from_utf8(baseClass()->prerequisites());
699 docstring const msg =
700 bformat(_("The selected document class\n"
702 "requires external files that are not available.\n"
703 "The document class can still be used, but the\n"
704 "document cannot be compiled until the following\n"
705 "prerequisites are installed:\n"
707 "See section 3.1.2.2 (Class Availability) of the\n"
708 "User's Guide for more information."), desc, prereqs);
709 frontend::Alert::warning(_("Document class not available"),
712 } else if (token == "\\save_transient_properties") {
713 lex >> save_transient_properties;
714 } else if (token == "\\origin") {
716 origin = lex.getString();
717 string const sysdirprefix = "/systemlyxdir/";
718 if (prefixIs(origin, sysdirprefix)) {
720 if (inSystemDir(filepath, docsys))
721 origin.replace(0, sysdirprefix.length() - 1, docsys);
723 origin.replace(0, sysdirprefix.length() - 1,
724 package().system_support().absFileName());
726 } else if (token == "\\begin_preamble") {
728 } else if (token == "\\begin_local_layout") {
729 readLocalLayout(lex, false);
730 } else if (token == "\\begin_forced_local_layout") {
731 readLocalLayout(lex, true);
732 } else if (token == "\\begin_modules") {
734 } else if (token == "\\begin_removed_modules") {
735 readRemovedModules(lex);
736 } else if (token == "\\begin_includeonly") {
737 readIncludeonly(lex);
738 } else if (token == "\\maintain_unincluded_children") {
739 lex >> maintain_unincluded_children;
740 } else if (token == "\\options") {
742 options = lex.getString();
743 } else if (token == "\\use_default_options") {
744 lex >> use_default_options;
745 } else if (token == "\\master") {
747 master = lex.getString();
748 if (!filepath.empty() && FileName::isAbsolute(origin)) {
749 bool const isabs = FileName::isAbsolute(master);
750 FileName const abspath(isabs ? master : origin + master);
751 bool const moved = filepath != FileName(origin);
752 if (moved && abspath.exists()) {
753 docstring const path = isabs
755 : from_utf8(abspath.realPath());
756 docstring const refpath =
757 from_utf8(filepath.absFileName());
758 master = to_utf8(makeRelPath(path, refpath));
761 } else if (token == "\\suppress_date") {
762 lex >> suppress_date;
763 } else if (token == "\\justification") {
764 lex >> justification;
765 } else if (token == "\\language") {
767 } else if (token == "\\language_package") {
769 lang_package = lex.getString();
770 } else if (token == "\\inputencoding") {
772 } else if (token == "\\graphics") {
773 readGraphicsDriver(lex);
774 } else if (token == "\\default_output_format") {
775 lex >> default_output_format;
776 } else if (token == "\\bibtex_command") {
778 bibtex_command = lex.getString();
779 } else if (token == "\\index_command") {
781 index_command = lex.getString();
782 } else if (token == "\\fontencoding") {
784 fontenc = lex.getString();
785 } else if (token == "\\font_roman") {
786 lex >> fonts_roman[0];
787 lex >> fonts_roman[1];
788 } else if (token == "\\font_sans") {
789 lex >> fonts_sans[0];
790 lex >> fonts_sans[1];
791 } else if (token == "\\font_typewriter") {
792 lex >> fonts_typewriter[0];
793 lex >> fonts_typewriter[1];
794 } else if (token == "\\font_math") {
795 lex >> fonts_math[0];
796 lex >> fonts_math[1];
797 } else if (token == "\\font_default_family") {
798 lex >> fonts_default_family;
799 } else if (token == "\\use_non_tex_fonts") {
800 lex >> useNonTeXFonts;
801 } else if (token == "\\font_sc") {
802 lex >> fonts_expert_sc;
803 } else if (token == "\\font_osf") {
804 lex >> fonts_old_figures;
805 } else if (token == "\\font_sf_scale") {
806 lex >> fonts_sans_scale[0];
807 lex >> fonts_sans_scale[1];
808 } else if (token == "\\font_tt_scale") {
809 lex >> fonts_typewriter_scale[0];
810 lex >> fonts_typewriter_scale[1];
811 } else if (token == "\\font_cjk") {
813 } else if (token == "\\use_microtype") {
814 lex >> use_microtype;
815 } else if (token == "\\paragraph_separation") {
818 paragraph_separation = parseptranslator().find(parsep);
819 } else if (token == "\\paragraph_indentation") {
821 string indentation = lex.getString();
822 pimpl_->indentation = HSpace(indentation);
823 } else if (token == "\\defskip") {
825 string const defskip = lex.getString();
826 pimpl_->defskip = VSpace(defskip);
827 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
829 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
830 } else if (token == "\\quotes_style") {
833 quotes_style = quotesstyletranslator().find(qstyle);
834 } else if (token == "\\dynamic_quotes") {
835 lex >> dynamic_quotes;
836 } else if (token == "\\papersize") {
839 papersize = papersizetranslator().find(ppsize);
840 } else if (token == "\\use_geometry") {
842 } else if (token == "\\use_package") {
847 use_package(package, packagetranslator().find(use));
848 } else if (token == "\\cite_engine") {
850 vector<string> engine = getVectorFromString(lex.getString());
851 setCiteEngine(engine);
852 } else if (token == "\\cite_engine_type") {
855 cite_engine_type_ = theCiteEnginesList.getType(engine_type);
856 } else if (token == "\\biblio_style") {
858 biblio_style = lex.getString();
859 } else if (token == "\\biblio_options") {
861 biblio_opts = trim(lex.getString());
862 } else if (token == "\\biblatex_bibstyle") {
864 biblatex_bibstyle = trim(lex.getString());
865 } else if (token == "\\biblatex_citestyle") {
867 biblatex_citestyle = trim(lex.getString());
868 } else if (token == "\\use_bibtopic") {
870 } else if (token == "\\multibib") {
872 } else if (token == "\\use_indices") {
874 } else if (token == "\\tracking_changes") {
875 lex >> track_changes;
876 } else if (token == "\\output_changes") {
877 lex >> output_changes;
878 } else if (token == "\\branch") {
880 docstring branch = lex.getDocString();
881 branchlist().add(branch);
884 string const tok = lex.getString();
885 if (tok == "\\end_branch")
887 Branch * branch_ptr = branchlist().find(branch);
888 if (tok == "\\selected") {
891 branch_ptr->setSelected(lex.getInteger());
893 if (tok == "\\filename_suffix") {
896 branch_ptr->setFileNameSuffix(lex.getInteger());
898 if (tok == "\\color") {
900 string color = lex.getString();
902 branch_ptr->setColor(color);
903 // Update also the Color table:
905 color = lcolor.getX11Name(Color_background);
907 lcolor.setColor(to_utf8(branch), color);
910 } else if (token == "\\index") {
912 docstring index = lex.getDocString();
914 indiceslist().add(index);
917 string const tok = lex.getString();
918 if (tok == "\\end_index")
920 Index * index_ptr = indiceslist().find(index);
921 if (tok == "\\shortcut") {
923 shortcut = lex.getDocString();
925 index_ptr->setShortcut(shortcut);
927 if (tok == "\\color") {
929 string color = lex.getString();
931 index_ptr->setColor(color);
932 // Update also the Color table:
934 color = lcolor.getX11Name(Color_background);
936 if (!shortcut.empty())
937 lcolor.setColor(to_utf8(shortcut), color);
940 } else if (token == "\\author") {
942 istringstream ss(lex.getString());
946 } else if (token == "\\paperorientation") {
949 orientation = paperorientationtranslator().find(orient);
950 } else if (token == "\\backgroundcolor") {
952 backgroundcolor = lyx::rgbFromHexName(lex.getString());
953 isbackgroundcolor = true;
954 } else if (token == "\\fontcolor") {
956 fontcolor = lyx::rgbFromHexName(lex.getString());
958 } else if (token == "\\notefontcolor") {
960 string color = lex.getString();
961 notefontcolor = lyx::rgbFromHexName(color);
962 lcolor.setColor("notefontcolor", color);
963 } else if (token == "\\boxbgcolor") {
965 string color = lex.getString();
966 boxbgcolor = lyx::rgbFromHexName(color);
967 lcolor.setColor("boxbgcolor", color);
968 } else if (token == "\\paperwidth") {
970 } else if (token == "\\paperheight") {
972 } else if (token == "\\leftmargin") {
974 } else if (token == "\\topmargin") {
976 } else if (token == "\\rightmargin") {
978 } else if (token == "\\bottommargin") {
980 } else if (token == "\\headheight") {
982 } else if (token == "\\headsep") {
984 } else if (token == "\\footskip") {
986 } else if (token == "\\columnsep") {
988 } else if (token == "\\paperfontsize") {
990 } else if (token == "\\papercolumns") {
992 } else if (token == "\\listings_params") {
995 listings_params = InsetListingsParams(par).params();
996 } else if (token == "\\papersides") {
999 sides = sidestranslator().find(psides);
1000 } else if (token == "\\paperpagestyle") {
1002 } else if (token == "\\bullet") {
1004 } else if (token == "\\bulletLaTeX") {
1005 readBulletsLaTeX(lex);
1006 } else if (token == "\\secnumdepth") {
1008 } else if (token == "\\tocdepth") {
1010 } else if (token == "\\spacing") {
1014 if (nspacing == "other") {
1017 spacing().set(spacetranslator().find(nspacing), tmp_val);
1018 } else if (token == "\\float_placement") {
1019 lex >> float_placement;
1021 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
1022 string toktmp = pdfoptions().readToken(lex, token);
1023 if (!toktmp.empty()) {
1024 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
1028 } else if (token == "\\html_math_output") {
1031 html_math_output = static_cast<MathOutput>(temp);
1032 } else if (token == "\\html_be_strict") {
1033 lex >> html_be_strict;
1034 } else if (token == "\\html_css_as_file") {
1035 lex >> html_css_as_file;
1036 } else if (token == "\\html_math_img_scale") {
1037 lex >> html_math_img_scale;
1038 } else if (token == "\\html_latex_start") {
1040 html_latex_start = lex.getString();
1041 } else if (token == "\\html_latex_end") {
1043 html_latex_end = lex.getString();
1044 } else if (token == "\\output_sync") {
1046 } else if (token == "\\output_sync_macro") {
1047 lex >> output_sync_macro;
1048 } else if (token == "\\use_refstyle") {
1049 lex >> use_refstyle;
1051 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1061 // Quote argument if it contains spaces
1062 string quoteIfNeeded(string const & str) {
1063 if (contains(str, ' '))
1064 return "\"" + str + "\"";
1070 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1072 // The top of the file is written by the buffer.
1073 // Prints out the buffer info into the .lyx file given by file
1075 os << "\\save_transient_properties "
1076 << convert<string>(save_transient_properties) << '\n';
1078 // the document directory (must end with a path separator)
1079 // realPath() is used to resolve symlinks, while addPath(..., "")
1080 // ensures a trailing path separator.
1082 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1083 string const sysdir = inSystemDir(FileName(filepath), docsys) ? docsys
1084 : addPath(package().system_support().realPath(), "");
1085 string const relpath =
1086 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1087 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1088 filepath = addPath("/systemlyxdir", relpath);
1089 else if (!save_transient_properties || !lyxrc.save_origin)
1090 filepath = "unavailable";
1091 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1094 os << "\\textclass "
1095 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1096 baseClass()->name()), "layout"))
1099 // then the preamble
1100 if (!preamble.empty()) {
1101 // remove '\n' from the end of preamble
1102 docstring const tmppreamble = rtrim(preamble, "\n");
1103 os << "\\begin_preamble\n"
1104 << to_utf8(tmppreamble)
1105 << "\n\\end_preamble\n";
1109 if (!options.empty()) {
1110 os << "\\options " << options << '\n';
1113 // use the class options defined in the layout?
1114 os << "\\use_default_options "
1115 << convert<string>(use_default_options) << "\n";
1117 // the master document
1118 if (!master.empty()) {
1119 os << "\\master " << master << '\n';
1123 if (!removed_modules_.empty()) {
1124 os << "\\begin_removed_modules" << '\n';
1125 list<string>::const_iterator it = removed_modules_.begin();
1126 list<string>::const_iterator en = removed_modules_.end();
1127 for (; it != en; ++it)
1129 os << "\\end_removed_modules" << '\n';
1133 if (!layout_modules_.empty()) {
1134 os << "\\begin_modules" << '\n';
1135 LayoutModuleList::const_iterator it = layout_modules_.begin();
1136 LayoutModuleList::const_iterator en = layout_modules_.end();
1137 for (; it != en; ++it)
1139 os << "\\end_modules" << '\n';
1143 if (!included_children_.empty()) {
1144 os << "\\begin_includeonly" << '\n';
1145 list<string>::const_iterator it = included_children_.begin();
1146 list<string>::const_iterator en = included_children_.end();
1147 for (; it != en; ++it)
1149 os << "\\end_includeonly" << '\n';
1151 os << "\\maintain_unincluded_children "
1152 << convert<string>(maintain_unincluded_children) << '\n';
1154 // local layout information
1155 docstring const local_layout = getLocalLayout(false);
1156 if (!local_layout.empty()) {
1157 // remove '\n' from the end
1158 docstring const tmplocal = rtrim(local_layout, "\n");
1159 os << "\\begin_local_layout\n"
1160 << to_utf8(tmplocal)
1161 << "\n\\end_local_layout\n";
1163 docstring const forced_local_layout = getLocalLayout(true);
1164 if (!forced_local_layout.empty()) {
1165 // remove '\n' from the end
1166 docstring const tmplocal = rtrim(forced_local_layout, "\n");
1167 os << "\\begin_forced_local_layout\n"
1168 << to_utf8(tmplocal)
1169 << "\n\\end_forced_local_layout\n";
1172 // then the text parameters
1173 if (language != ignore_language)
1174 os << "\\language " << language->lang() << '\n';
1175 os << "\\language_package " << lang_package
1176 << "\n\\inputencoding " << inputenc
1177 << "\n\\fontencoding " << fontenc
1178 << "\n\\font_roman \"" << fonts_roman[0]
1179 << "\" \"" << fonts_roman[1] << '"'
1180 << "\n\\font_sans \"" << fonts_sans[0]
1181 << "\" \"" << fonts_sans[1] << '"'
1182 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1183 << "\" \"" << fonts_typewriter[1] << '"'
1184 << "\n\\font_math \"" << fonts_math[0]
1185 << "\" \"" << fonts_math[1] << '"'
1186 << "\n\\font_default_family " << fonts_default_family
1187 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1188 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1189 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1190 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1191 << ' ' << fonts_sans_scale[1]
1192 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1193 << ' ' << fonts_typewriter_scale[1]
1195 if (!fonts_cjk.empty()) {
1196 os << "\\font_cjk " << fonts_cjk << '\n';
1198 os << "\\use_microtype " << convert<string>(use_microtype) << '\n';
1199 os << "\\graphics " << graphics_driver << '\n';
1200 os << "\\default_output_format " << default_output_format << '\n';
1201 os << "\\output_sync " << output_sync << '\n';
1202 if (!output_sync_macro.empty())
1203 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1204 os << "\\bibtex_command " << bibtex_command << '\n';
1205 os << "\\index_command " << index_command << '\n';
1207 if (!float_placement.empty()) {
1208 os << "\\float_placement " << float_placement << '\n';
1210 os << "\\paperfontsize " << fontsize << '\n';
1212 spacing().writeFile(os);
1213 pdfoptions().writeFile(os);
1215 os << "\\papersize " << string_papersize[papersize]
1216 << "\n\\use_geometry " << convert<string>(use_geometry);
1217 map<string, string> const & packages = auto_packages();
1218 for (map<string, string>::const_iterator it = packages.begin();
1219 it != packages.end(); ++it)
1220 os << "\n\\use_package " << it->first << ' '
1221 << use_package(it->first);
1223 os << "\n\\cite_engine ";
1225 if (!cite_engine_.empty()) {
1226 LayoutModuleList::const_iterator be = cite_engine_.begin();
1227 LayoutModuleList::const_iterator en = cite_engine_.end();
1228 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1237 os << "\n\\cite_engine_type " << theCiteEnginesList.getTypeAsString(cite_engine_type_);
1239 if (!biblio_style.empty())
1240 os << "\n\\biblio_style " << biblio_style;
1241 if (!biblio_opts.empty())
1242 os << "\n\\biblio_options " << biblio_opts;
1243 if (!biblatex_bibstyle.empty())
1244 os << "\n\\biblatex_bibstyle " << biblatex_bibstyle;
1245 if (!biblatex_citestyle.empty())
1246 os << "\n\\biblatex_citestyle " << biblatex_citestyle;
1247 if (!multibib.empty())
1248 os << "\n\\multibib " << multibib;
1250 os << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1251 << "\n\\use_indices " << convert<string>(use_indices)
1252 << "\n\\paperorientation " << string_orientation[orientation]
1253 << "\n\\suppress_date " << convert<string>(suppress_date)
1254 << "\n\\justification " << convert<string>(justification)
1255 << "\n\\use_refstyle " << use_refstyle
1257 if (isbackgroundcolor == true)
1258 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1259 if (isfontcolor == true)
1260 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1261 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1262 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1263 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1264 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1266 BranchList::const_iterator it = branchlist().begin();
1267 BranchList::const_iterator end = branchlist().end();
1268 for (; it != end; ++it) {
1269 os << "\\branch " << to_utf8(it->branch())
1270 << "\n\\selected " << it->isSelected()
1271 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1272 << "\n\\color " << lyx::X11hexname(it->color())
1277 IndicesList::const_iterator iit = indiceslist().begin();
1278 IndicesList::const_iterator iend = indiceslist().end();
1279 for (; iit != iend; ++iit) {
1280 os << "\\index " << to_utf8(iit->index())
1281 << "\n\\shortcut " << to_utf8(iit->shortcut())
1282 << "\n\\color " << lyx::X11hexname(iit->color())
1287 if (!paperwidth.empty())
1288 os << "\\paperwidth "
1289 << VSpace(paperwidth).asLyXCommand() << '\n';
1290 if (!paperheight.empty())
1291 os << "\\paperheight "
1292 << VSpace(paperheight).asLyXCommand() << '\n';
1293 if (!leftmargin.empty())
1294 os << "\\leftmargin "
1295 << VSpace(leftmargin).asLyXCommand() << '\n';
1296 if (!topmargin.empty())
1297 os << "\\topmargin "
1298 << VSpace(topmargin).asLyXCommand() << '\n';
1299 if (!rightmargin.empty())
1300 os << "\\rightmargin "
1301 << VSpace(rightmargin).asLyXCommand() << '\n';
1302 if (!bottommargin.empty())
1303 os << "\\bottommargin "
1304 << VSpace(bottommargin).asLyXCommand() << '\n';
1305 if (!headheight.empty())
1306 os << "\\headheight "
1307 << VSpace(headheight).asLyXCommand() << '\n';
1308 if (!headsep.empty())
1310 << VSpace(headsep).asLyXCommand() << '\n';
1311 if (!footskip.empty())
1313 << VSpace(footskip).asLyXCommand() << '\n';
1314 if (!columnsep.empty())
1315 os << "\\columnsep "
1316 << VSpace(columnsep).asLyXCommand() << '\n';
1317 os << "\\secnumdepth " << secnumdepth
1318 << "\n\\tocdepth " << tocdepth
1319 << "\n\\paragraph_separation "
1320 << string_paragraph_separation[paragraph_separation];
1321 if (!paragraph_separation)
1322 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1324 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1325 os << "\n\\quotes_style "
1326 << string_quotes_style[quotes_style]
1327 << "\n\\dynamic_quotes " << dynamic_quotes
1328 << "\n\\papercolumns " << columns
1329 << "\n\\papersides " << sides
1330 << "\n\\paperpagestyle " << pagestyle << '\n';
1331 if (!listings_params.empty())
1332 os << "\\listings_params \"" <<
1333 InsetListingsParams(listings_params).encodedString() << "\"\n";
1334 for (int i = 0; i < 4; ++i) {
1335 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1336 if (user_defined_bullet(i).getFont() != -1) {
1337 os << "\\bullet " << i << " "
1338 << user_defined_bullet(i).getFont() << " "
1339 << user_defined_bullet(i).getCharacter() << " "
1340 << user_defined_bullet(i).getSize() << "\n";
1344 os << "\\bulletLaTeX " << i << " \""
1345 << lyx::to_ascii(user_defined_bullet(i).getText())
1351 os << "\\tracking_changes "
1352 << (save_transient_properties ? convert<string>(track_changes) : "false")
1355 os << "\\output_changes "
1356 << (save_transient_properties ? convert<string>(output_changes) : "false")
1359 os << "\\html_math_output " << html_math_output << '\n'
1360 << "\\html_css_as_file " << html_css_as_file << '\n'
1361 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1363 if (html_math_img_scale != 1.0)
1364 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1365 if (!html_latex_start.empty())
1366 os << "\\html_latex_start " << html_latex_start << '\n';
1367 if (!html_latex_end.empty())
1368 os << "\\html_latex_end " << html_latex_end << '\n';
1370 os << pimpl_->authorlist;
1374 void BufferParams::validate(LaTeXFeatures & features) const
1376 features.require(documentClass().requires());
1378 if (columns > 1 && language->rightToLeft())
1379 features.require("rtloutputdblcol");
1381 if (output_changes) {
1382 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1383 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1384 LaTeXFeatures::isAvailable("xcolor");
1386 switch (features.runparams().flavor) {
1387 case OutputParams::LATEX:
1388 case OutputParams::DVILUATEX:
1390 features.require("ct-dvipost");
1391 features.require("dvipost");
1392 } else if (xcolorulem) {
1393 features.require("ct-xcolor-ulem");
1394 features.require("ulem");
1395 features.require("xcolor");
1397 features.require("ct-none");
1400 case OutputParams::LUATEX:
1401 case OutputParams::PDFLATEX:
1402 case OutputParams::XETEX:
1404 features.require("ct-xcolor-ulem");
1405 features.require("ulem");
1406 features.require("xcolor");
1407 // improves color handling in PDF output
1408 features.require("pdfcolmk");
1410 features.require("ct-none");
1418 // Floats with 'Here definitely' as default setting.
1419 if (float_placement.find('H') != string::npos)
1420 features.require("float");
1422 for (PackageMap::const_iterator it = use_packages.begin();
1423 it != use_packages.end(); ++it) {
1424 if (it->first == "amsmath") {
1425 // AMS Style is at document level
1426 if (it->second == package_on ||
1427 features.isProvided("amsmath"))
1428 features.require(it->first);
1429 } else if (it->second == package_on)
1430 features.require(it->first);
1433 // Document-level line spacing
1434 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1435 features.require("setspace");
1437 // the bullet shapes are buffer level not paragraph level
1438 // so they are tested here
1439 for (int i = 0; i < 4; ++i) {
1440 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1442 int const font = user_defined_bullet(i).getFont();
1444 int const c = user_defined_bullet(i).getCharacter();
1450 features.require("latexsym");
1452 } else if (font == 1) {
1453 features.require("amssymb");
1454 } else if (font >= 2 && font <= 5) {
1455 features.require("pifont");
1459 if (pdfoptions().use_hyperref) {
1460 features.require("hyperref");
1461 // due to interferences with babel and hyperref, the color package has to
1462 // be loaded after hyperref when hyperref is used with the colorlinks
1463 // option, see http://www.lyx.org/trac/ticket/5291
1464 if (pdfoptions().colorlinks)
1465 features.require("color");
1467 if (!listings_params.empty()) {
1468 // do not test validity because listings_params is
1469 // supposed to be valid
1471 InsetListingsParams(listings_params).separatedParams(true);
1472 // we can't support all packages, but we should load the color package
1473 if (par.find("\\color", 0) != string::npos)
1474 features.require("color");
1477 // some languages are only available via polyglossia
1478 if (features.hasPolyglossiaExclusiveLanguages())
1479 features.require("polyglossia");
1481 if (useNonTeXFonts && fontsMath() != "auto")
1482 features.require("unicode-math");
1485 features.require("microtype");
1487 if (!language->requires().empty())
1488 features.require(language->requires());
1492 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1493 FileName const & filepath) const
1495 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1496 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1497 // \RequirePackage to do so, rather than the normal \usepackage
1498 // Do not try to load any other package before the document class, unless you
1499 // have a thorough understanding of the LATEX internals and know exactly what you
1501 if (features.mustProvide("fix-cm"))
1502 os << "\\RequirePackage{fix-cm}\n";
1503 // Likewise for fixltx2e. If other packages conflict with this policy,
1504 // treat it as a package bug (and report it!)
1505 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1506 if (features.mustProvide("fixltx2e"))
1507 os << "\\RequirePackage{fixltx2e}\n";
1509 os << "\\documentclass";
1511 DocumentClass const & tclass = documentClass();
1513 ostringstream clsoptions; // the document class options.
1515 if (tokenPos(tclass.opt_fontsize(),
1516 '|', fontsize) >= 0) {
1517 // only write if existing in list (and not default)
1518 clsoptions << fontsize << "pt,";
1521 // all paper sizes except of A4, A5, B5 and the US sizes need the
1523 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1524 && papersize != PAPER_USLETTER
1525 && papersize != PAPER_USLEGAL
1526 && papersize != PAPER_USEXECUTIVE
1527 && papersize != PAPER_A4
1528 && papersize != PAPER_A5
1529 && papersize != PAPER_B5;
1531 if (!use_geometry) {
1532 switch (papersize) {
1534 clsoptions << "a4paper,";
1536 case PAPER_USLETTER:
1537 clsoptions << "letterpaper,";
1540 clsoptions << "a5paper,";
1543 clsoptions << "b5paper,";
1545 case PAPER_USEXECUTIVE:
1546 clsoptions << "executivepaper,";
1549 clsoptions << "legalpaper,";
1583 if (sides != tclass.sides()) {
1586 clsoptions << "oneside,";
1589 clsoptions << "twoside,";
1595 if (columns != tclass.columns()) {
1597 clsoptions << "twocolumn,";
1599 clsoptions << "onecolumn,";
1603 && orientation == ORIENTATION_LANDSCAPE)
1604 clsoptions << "landscape,";
1606 // language should be a parameter to \documentclass
1607 if (language->babel() == "hebrew"
1608 && default_language->babel() != "hebrew")
1609 // This seems necessary
1610 features.useLanguage(default_language);
1612 ostringstream language_options;
1613 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1614 bool const use_polyglossia = features.usePolyglossia();
1615 bool const global = lyxrc.language_global_options;
1616 if (use_babel || (use_polyglossia && global)) {
1617 language_options << features.getBabelLanguages();
1618 if (!language->babel().empty()) {
1619 if (!language_options.str().empty())
1620 language_options << ',';
1621 language_options << language->babel();
1623 if (global && !features.needBabelLangOptions()
1624 && !language_options.str().empty())
1625 clsoptions << language_options.str() << ',';
1628 // the predefined options from the layout
1629 if (use_default_options && !tclass.options().empty())
1630 clsoptions << tclass.options() << ',';
1632 // the user-defined options
1633 if (!options.empty()) {
1634 clsoptions << options << ',';
1637 string strOptions(clsoptions.str());
1638 if (!strOptions.empty()) {
1639 strOptions = rtrim(strOptions, ",");
1641 os << '[' << from_utf8(strOptions) << ']';
1644 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1645 // end of \documentclass defs
1647 // if we use fontspec or newtxmath, we have to load the AMS packages here
1648 string const ams = features.loadAMSPackages();
1649 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1650 bool const use_newtxmath =
1651 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1652 ot1, false, false) == "newtxmath";
1653 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1654 os << from_ascii(ams);
1656 if (useNonTeXFonts) {
1657 if (!features.isProvided("fontspec"))
1658 os << "\\usepackage{fontspec}\n";
1659 if (features.mustProvide("unicode-math")
1660 && features.isAvailable("unicode-math"))
1661 os << "\\usepackage{unicode-math}\n";
1664 // font selection must be done before loading fontenc.sty
1665 string const fonts = loadFonts(features);
1667 os << from_utf8(fonts);
1669 if (fonts_default_family != "default")
1670 os << "\\renewcommand{\\familydefault}{\\"
1671 << from_ascii(fonts_default_family) << "}\n";
1673 // set font encoding
1674 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1675 if (!useNonTeXFonts && !features.isProvided("fontenc")
1676 && font_encoding() != "default") {
1677 // get main font encodings
1678 vector<string> fontencs = font_encodings();
1679 // get font encodings of secondary languages
1680 features.getFontEncodings(fontencs);
1681 if (!fontencs.empty()) {
1682 os << "\\usepackage["
1683 << from_ascii(getStringFromVector(fontencs))
1688 // handle inputenc etc.
1689 writeEncodingPreamble(os, features);
1692 if (!features.runparams().includeall && !included_children_.empty()) {
1693 os << "\\includeonly{";
1694 list<string>::const_iterator it = included_children_.begin();
1695 list<string>::const_iterator en = included_children_.end();
1697 for (; it != en; ++it) {
1698 string incfile = *it;
1699 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1700 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1702 if (!features.runparams().nice)
1704 // \includeonly doesn't want an extension
1705 incfile = changeExtension(incfile, string());
1706 incfile = support::latex_path(incfile);
1707 if (!incfile.empty()) {
1710 os << from_utf8(incfile);
1717 if (!features.isProvided("geometry")
1718 && (use_geometry || nonstandard_papersize)) {
1719 odocstringstream ods;
1720 if (!getGraphicsDriver("geometry").empty())
1721 ods << getGraphicsDriver("geometry");
1722 if (orientation == ORIENTATION_LANDSCAPE)
1723 ods << ",landscape";
1724 switch (papersize) {
1726 if (!paperwidth.empty())
1727 ods << ",paperwidth="
1728 << from_ascii(paperwidth);
1729 if (!paperheight.empty())
1730 ods << ",paperheight="
1731 << from_ascii(paperheight);
1733 case PAPER_USLETTER:
1734 ods << ",letterpaper";
1737 ods << ",legalpaper";
1739 case PAPER_USEXECUTIVE:
1740 ods << ",executivepaper";
1829 docstring const g_options = trim(ods.str(), ",");
1830 os << "\\usepackage";
1831 if (!g_options.empty())
1832 os << '[' << g_options << ']';
1833 os << "{geometry}\n";
1834 // output this only if use_geometry is true
1836 os << "\\geometry{verbose";
1837 if (!topmargin.empty())
1838 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1839 if (!bottommargin.empty())
1840 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1841 if (!leftmargin.empty())
1842 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1843 if (!rightmargin.empty())
1844 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1845 if (!headheight.empty())
1846 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1847 if (!headsep.empty())
1848 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1849 if (!footskip.empty())
1850 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1851 if (!columnsep.empty())
1852 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1855 } else if (orientation == ORIENTATION_LANDSCAPE
1856 || papersize != PAPER_DEFAULT) {
1857 features.require("papersize");
1860 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1861 if (pagestyle == "fancy")
1862 os << "\\usepackage{fancyhdr}\n";
1863 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1866 // only output when the background color is not default
1867 if (isbackgroundcolor == true) {
1868 // only require color here, the background color will be defined
1869 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1871 features.require("color");
1872 features.require("pagecolor");
1875 // only output when the font color is not default
1876 if (isfontcolor == true) {
1877 // only require color here, the font color will be defined
1878 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1880 features.require("color");
1881 features.require("fontcolor");
1884 // Only if class has a ToC hierarchy
1885 if (tclass.hasTocLevels()) {
1886 if (secnumdepth != tclass.secnumdepth()) {
1887 os << "\\setcounter{secnumdepth}{"
1891 if (tocdepth != tclass.tocdepth()) {
1892 os << "\\setcounter{tocdepth}{"
1898 if (paragraph_separation) {
1899 // when skip separation
1900 switch (getDefSkip().kind()) {
1901 case VSpace::SMALLSKIP:
1902 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1904 case VSpace::MEDSKIP:
1905 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1907 case VSpace::BIGSKIP:
1908 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1910 case VSpace::LENGTH:
1911 os << "\\setlength{\\parskip}{"
1912 << from_utf8(getDefSkip().length().asLatexString())
1915 default: // should never happen // Then delete it.
1916 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1919 os << "\\setlength{\\parindent}{0pt}\n";
1921 // when separation by indentation
1922 // only output something when a width is given
1923 if (getIndentation().asLyXCommand() != "default") {
1924 os << "\\setlength{\\parindent}{"
1925 << from_utf8(getIndentation().asLatexCommand())
1930 // Now insert the LyX specific LaTeX commands...
1931 features.resolveAlternatives();
1932 features.expandMultiples();
1935 if (!output_sync_macro.empty())
1936 os << from_utf8(output_sync_macro) +"\n";
1937 else if (features.runparams().flavor == OutputParams::LATEX)
1938 os << "\\usepackage[active]{srcltx}\n";
1939 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1940 os << "\\synctex=-1\n";
1943 // The package options (via \PassOptionsToPackage)
1944 os << from_ascii(features.getPackageOptions());
1946 // due to interferences with babel and hyperref, the color package has to
1947 // be loaded (when it is not already loaded) before babel when hyperref
1948 // is used with the colorlinks option, see
1949 // http://www.lyx.org/trac/ticket/5291
1950 // we decided therefore to load color always before babel, see
1951 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1952 os << from_ascii(features.getColorOptions());
1954 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1955 // we have to call babel before
1957 && (features.isRequired("jurabib")
1958 || features.isRequired("hyperref")
1959 || features.isRequired("varioref")
1960 || features.isRequired("vietnamese")
1961 || features.isRequired("japanese"))) {
1962 os << features.getBabelPresettings();
1964 os << from_utf8(babelCall(language_options.str(),
1965 features.needBabelLangOptions())) + '\n';
1966 os << features.getBabelPostsettings();
1969 // The optional packages;
1970 os << from_ascii(features.getPackages());
1972 // Additional Indices
1973 if (features.isRequired("splitidx")) {
1974 IndicesList::const_iterator iit = indiceslist().begin();
1975 IndicesList::const_iterator iend = indiceslist().end();
1976 for (; iit != iend; ++iit) {
1977 os << "\\newindex{";
1978 os << escape(iit->shortcut());
1984 os << from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1987 // * Hyperref manual: "Make sure it comes last of your loaded
1988 // packages, to give it a fighting chance of not being over-written,
1989 // since its job is to redefine many LaTeX commands."
1990 // * Email from Heiko Oberdiek: "It is usually better to load babel
1991 // before hyperref. Then hyperref has a chance to detect babel.
1992 // * Has to be loaded before the "LyX specific LaTeX commands" to
1993 // avoid errors with algorithm floats.
1994 // use hyperref explicitly if it is required
1995 if (features.isRequired("hyperref")) {
1996 OutputParams tmp_params = features.runparams();
1997 pdfoptions().writeLaTeX(tmp_params, os,
1998 features.isProvided("hyperref"));
1999 // correctly break URLs with hyperref and dvi output
2000 if (features.runparams().flavor == OutputParams::LATEX
2001 && features.isAvailable("breakurl"))
2002 os << "\\usepackage{breakurl}\n";
2003 } else if (features.isRequired("nameref"))
2004 // hyperref loads this automatically
2005 os << "\\usepackage{nameref}\n";
2007 // bibtopic needs to be loaded after hyperref.
2008 // the dot provides the aux file naming which LyX can detect.
2009 if (features.mustProvide("bibtopic"))
2010 os << "\\usepackage[dot]{bibtopic}\n";
2012 // Will be surrounded by \makeatletter and \makeatother when not empty
2013 otexstringstream atlyxpreamble;
2015 // Some macros LyX will need
2017 TexString tmppreamble = features.getMacros();
2018 if (!tmppreamble.str.empty())
2019 atlyxpreamble << "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2020 "LyX specific LaTeX commands.\n"
2021 << move(tmppreamble)
2024 // the text class specific preamble
2026 docstring tmppreamble = features.getTClassPreamble();
2027 if (!tmppreamble.empty())
2028 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2029 "Textclass specific LaTeX commands.\n"
2033 // suppress date if selected
2034 // use \@ifundefined because we cannot be sure that every document class
2035 // has a \date command
2037 atlyxpreamble << "\\@ifundefined{date}{}{\\date{}}\n";
2039 /* the user-defined preamble */
2040 if (!containsOnly(preamble, " \n\t")) {
2042 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2043 "User specified LaTeX commands.\n";
2045 // Check if the user preamble contains uncodable glyphs
2046 odocstringstream user_preamble;
2047 docstring uncodable_glyphs;
2048 Encoding const * const enc = features.runparams().encoding;
2050 for (size_t n = 0; n < preamble.size(); ++n) {
2051 char_type c = preamble[n];
2052 if (!enc->encodable(c)) {
2053 docstring const glyph(1, c);
2054 LYXERR0("Uncodable character '"
2056 << "' in user preamble!");
2057 uncodable_glyphs += glyph;
2058 if (features.runparams().dryrun) {
2059 user_preamble << "<" << _("LyX Warning: ")
2060 << _("uncodable character") << " '";
2061 user_preamble.put(c);
2062 user_preamble << "'>";
2065 user_preamble.put(c);
2068 user_preamble << preamble;
2070 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2071 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2072 frontend::Alert::warning(
2073 _("Uncodable character in user preamble"),
2075 _("The user preamble of your document contains glyphs "
2076 "that are unknown in the current document encoding "
2077 "(namely %1$s).\nThese glyphs are omitted "
2078 " from the output, which may result in "
2079 "incomplete output."
2080 "\n\nPlease select an appropriate "
2081 "document encoding\n"
2082 "(such as utf8) or change the "
2083 "preamble code accordingly."),
2086 atlyxpreamble << user_preamble.str() << '\n';
2089 // footmisc must be loaded after setspace
2090 // Load it here to avoid clashes with footmisc loaded in the user
2091 // preamble. For that reason we also pass the options via
2092 // \PassOptionsToPackage in getPreamble() and not here.
2093 if (features.mustProvide("footmisc"))
2094 atlyxpreamble << "\\usepackage{footmisc}\n";
2096 // subfig loads internally the LaTeX package "caption". As
2097 // caption is a very popular package, users will load it in
2098 // the preamble. Therefore we must load subfig behind the
2099 // user-defined preamble and check if the caption package was
2100 // loaded or not. For the case that caption is loaded before
2101 // subfig, there is the subfig option "caption=false". This
2102 // option also works when a koma-script class is used and
2103 // koma's own caption commands are used instead of caption. We
2104 // use \PassOptionsToPackage here because the user could have
2105 // already loaded subfig in the preamble.
2106 if (features.mustProvide("subfig"))
2107 atlyxpreamble << "\\@ifundefined{showcaptionsetup}{}{%\n"
2108 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2109 "\\usepackage{subfig}\n";
2111 // Itemize bullet settings need to be last in case the user
2112 // defines their own bullets that use a package included
2113 // in the user-defined preamble -- ARRae
2114 // Actually it has to be done much later than that
2115 // since some packages like frenchb make modifications
2116 // at \begin{document} time -- JMarc
2117 docstring bullets_def;
2118 for (int i = 0; i < 4; ++i) {
2119 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2120 if (bullets_def.empty())
2121 bullets_def += "\\AtBeginDocument{\n";
2122 bullets_def += " \\def\\labelitemi";
2124 // `i' is one less than the item to modify
2131 bullets_def += "ii";
2137 bullets_def += '{' +
2138 user_defined_bullet(i).getText()
2143 if (!bullets_def.empty())
2144 atlyxpreamble << bullets_def << "}\n\n";
2146 if (!atlyxpreamble.empty())
2147 os << "\n\\makeatletter\n"
2148 << atlyxpreamble.release()
2149 << "\\makeatother\n\n";
2151 // We try to load babel late, in case it interferes with other packages.
2152 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2153 // called after babel, though.
2154 if (use_babel && !features.isRequired("jurabib")
2155 && !features.isRequired("hyperref")
2156 && !features.isRequired("varioref")
2157 && !features.isRequired("vietnamese")
2158 && !features.isRequired("japanese")) {
2159 os << features.getBabelPresettings();
2161 os << from_utf8(babelCall(language_options.str(),
2162 features.needBabelLangOptions())) + '\n';
2163 os << features.getBabelPostsettings();
2165 if (features.isRequired("bicaption"))
2166 os << "\\usepackage{bicaption}\n";
2167 if (!listings_params.empty() || features.mustProvide("listings"))
2168 os << "\\usepackage{listings}\n";
2169 if (!listings_params.empty()) {
2171 // do not test validity because listings_params is
2172 // supposed to be valid
2174 InsetListingsParams(listings_params).separatedParams(true);
2175 os << from_utf8(par);
2179 // xunicode needs to be loaded at least after amsmath, amssymb,
2180 // esint and the other packages that provide special glyphs
2181 // The package only supports XeTeX currently.
2182 if (features.runparams().flavor == OutputParams::XETEX
2184 os << "\\usepackage{xunicode}\n";
2186 // Polyglossia must be loaded last ...
2187 if (use_polyglossia) {
2189 os << "\\usepackage{polyglossia}\n";
2190 // set the main language
2191 os << "\\setdefaultlanguage";
2192 if (!language->polyglossiaOpts().empty())
2193 os << "[" << from_ascii(language->polyglossiaOpts()) << "]";
2194 os << "{" << from_ascii(language->polyglossia()) << "}\n";
2195 // now setup the other languages
2196 set<string> const polylangs =
2197 features.getPolyglossiaLanguages();
2198 for (set<string>::const_iterator mit = polylangs.begin();
2199 mit != polylangs.end() ; ++mit) {
2200 // We do not output the options here; they are output in
2201 // the language switch commands. This is safer if multiple
2202 // varieties are used.
2203 if (*mit == language->polyglossia())
2205 os << "\\setotherlanguage";
2206 os << "{" << from_ascii(*mit) << "}\n";
2210 // ... but before biblatex (see #7065)
2211 if (features.mustProvide("biblatex")) {
2214 os << "\\usepackage";
2215 if (!biblatex_bibstyle.empty()
2216 && (biblatex_bibstyle == biblatex_citestyle)) {
2217 opts = "style=" + biblatex_bibstyle;
2220 if (!biblatex_bibstyle.empty()) {
2221 opts = "bibstyle=" + biblatex_bibstyle;
2224 if (!biblatex_citestyle.empty()) {
2225 opts += delim + "citestyle=" + biblatex_citestyle;
2229 if (!multibib.empty() && multibib != "child") {
2230 opts += delim + "refsection=" + multibib;
2233 if (bibtexCommand() == "bibtex8"
2234 || prefixIs(bibtexCommand(), "bibtex8 ")) {
2235 opts += delim + "backend=bibtex8";
2237 } else if (bibtexCommand() == "bibtex"
2238 || prefixIs(bibtexCommand(), "bibtex ")) {
2239 opts += delim + "backend=bibtex";
2242 if (!biblio_opts.empty())
2243 opts += delim + biblio_opts;
2245 os << "[" << opts << "]";
2246 os << "{biblatex}\n";
2250 // Load custom language package here
2251 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2252 if (lang_package == "default")
2253 os << from_utf8(lyxrc.language_custom_package);
2255 os << from_utf8(lang_package);
2259 docstring const i18npreamble =
2260 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2261 if (!i18npreamble.empty())
2262 os << i18npreamble + '\n';
2268 void BufferParams::useClassDefaults()
2270 DocumentClass const & tclass = documentClass();
2272 sides = tclass.sides();
2273 columns = tclass.columns();
2274 pagestyle = tclass.pagestyle();
2275 use_default_options = true;
2276 // Only if class has a ToC hierarchy
2277 if (tclass.hasTocLevels()) {
2278 secnumdepth = tclass.secnumdepth();
2279 tocdepth = tclass.tocdepth();
2284 bool BufferParams::hasClassDefaults() const
2286 DocumentClass const & tclass = documentClass();
2288 return sides == tclass.sides()
2289 && columns == tclass.columns()
2290 && pagestyle == tclass.pagestyle()
2291 && use_default_options
2292 && secnumdepth == tclass.secnumdepth()
2293 && tocdepth == tclass.tocdepth();
2297 DocumentClass const & BufferParams::documentClass() const
2303 DocumentClassConstPtr BufferParams::documentClassPtr() const
2309 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2311 // evil, but this function is evil
2312 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2313 invalidateConverterCache();
2317 bool BufferParams::setBaseClass(string const & classname)
2319 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2320 LayoutFileList & bcl = LayoutFileList::get();
2321 if (!bcl.haveClass(classname)) {
2323 bformat(_("The layout file:\n"
2325 "could not be found. A default textclass with default\n"
2326 "layouts will be used. LyX will not be able to produce\n"
2328 from_utf8(classname));
2329 frontend::Alert::error(_("Document class not found"), s);
2330 bcl.addEmptyClass(classname);
2333 bool const success = bcl[classname].load();
2336 bformat(_("Due to some error in it, the layout file:\n"
2338 "could not be loaded. A default textclass with default\n"
2339 "layouts will be used. LyX will not be able to produce\n"
2341 from_utf8(classname));
2342 frontend::Alert::error(_("Could not load class"), s);
2343 bcl.addEmptyClass(classname);
2346 pimpl_->baseClass_ = classname;
2347 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2352 LayoutFile const * BufferParams::baseClass() const
2354 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2355 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2361 LayoutFileIndex const & BufferParams::baseClassID() const
2363 return pimpl_->baseClass_;
2367 void BufferParams::makeDocumentClass(bool const clone)
2372 invalidateConverterCache();
2373 LayoutModuleList mods;
2374 LayoutModuleList ces;
2375 LayoutModuleList::iterator it = layout_modules_.begin();
2376 LayoutModuleList::iterator en = layout_modules_.end();
2377 for (; it != en; ++it)
2378 mods.push_back(*it);
2380 it = cite_engine_.begin();
2381 en = cite_engine_.end();
2382 for (; it != en; ++it)
2385 doc_class_ = getDocumentClass(*baseClass(), mods, ces, clone);
2387 TextClass::ReturnValues success = TextClass::OK;
2388 if (!forced_local_layout_.empty())
2389 success = doc_class_->read(to_utf8(forced_local_layout_),
2391 if (!local_layout_.empty() &&
2392 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2393 success = doc_class_->read(to_utf8(local_layout_), TextClass::MODULE);
2394 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2395 docstring const msg = _("Error reading internal layout information");
2396 frontend::Alert::warning(_("Read Error"), msg);
2401 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2403 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2407 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2409 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2413 docstring BufferParams::getLocalLayout(bool forced) const
2416 return from_utf8(doc_class_->forcedLayouts());
2418 return local_layout_;
2422 void BufferParams::setLocalLayout(docstring const & layout, bool forced)
2425 forced_local_layout_ = layout;
2427 local_layout_ = layout;
2431 bool BufferParams::addLayoutModule(string const & modName)
2433 LayoutModuleList::const_iterator it = layout_modules_.begin();
2434 LayoutModuleList::const_iterator end = layout_modules_.end();
2435 for (; it != end; ++it)
2438 layout_modules_.push_back(modName);
2443 string BufferParams::bufferFormat() const
2445 return documentClass().outputFormat();
2449 bool BufferParams::isExportable(string const & format, bool need_viewable) const
2451 FormatList const & formats = exportableFormats(need_viewable);
2452 FormatList::const_iterator fit = formats.begin();
2453 FormatList::const_iterator end = formats.end();
2454 for (; fit != end ; ++fit) {
2455 if ((*fit)->name() == format)
2462 FormatList const & BufferParams::exportableFormats(bool only_viewable) const
2464 FormatList & cached = only_viewable ?
2465 pimpl_->viewableFormatList : pimpl_->exportableFormatList;
2466 bool & valid = only_viewable ?
2467 pimpl_->isViewCacheValid : pimpl_->isExportCacheValid;
2471 vector<string> const backs = backends();
2472 set<string> excludes;
2473 if (useNonTeXFonts) {
2474 excludes.insert("latex");
2475 excludes.insert("pdflatex");
2478 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2479 for (vector<string>::const_iterator it = backs.begin() + 1;
2480 it != backs.end(); ++it) {
2481 FormatList r = theConverters().getReachable(*it, only_viewable,
2483 result.insert(result.end(), r.begin(), r.end());
2485 sort(result.begin(), result.end(), Format::formatSorter);
2492 vector<string> BufferParams::backends() const
2495 string const buffmt = bufferFormat();
2497 // FIXME: Don't hardcode format names here, but use a flag
2498 if (buffmt == "latex") {
2499 if (encoding().package() == Encoding::japanese)
2500 v.push_back("platex");
2502 if (!useNonTeXFonts) {
2503 v.push_back("pdflatex");
2504 v.push_back("latex");
2506 v.push_back("xetex");
2507 v.push_back("luatex");
2508 v.push_back("dviluatex");
2511 v.push_back(buffmt);
2513 v.push_back("xhtml");
2514 v.push_back("text");
2520 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2522 string const dformat = (format.empty() || format == "default") ?
2523 getDefaultOutputFormat() : format;
2524 DefaultFlavorCache::const_iterator it =
2525 default_flavors_.find(dformat);
2527 if (it != default_flavors_.end())
2530 OutputParams::FLAVOR result = OutputParams::LATEX;
2532 // FIXME It'd be better not to hardcode this, but to do
2533 // something with formats.
2534 if (dformat == "xhtml")
2535 result = OutputParams::HTML;
2536 else if (dformat == "text")
2537 result = OutputParams::TEXT;
2538 else if (dformat == "lyx")
2539 result = OutputParams::LYX;
2540 else if (dformat == "pdflatex")
2541 result = OutputParams::PDFLATEX;
2542 else if (dformat == "xetex")
2543 result = OutputParams::XETEX;
2544 else if (dformat == "luatex")
2545 result = OutputParams::LUATEX;
2546 else if (dformat == "dviluatex")
2547 result = OutputParams::DVILUATEX;
2549 // Try to determine flavor of default output format
2550 vector<string> backs = backends();
2551 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2552 // Get shortest path to format
2553 Graph::EdgePath path;
2554 for (vector<string>::const_iterator it = backs.begin();
2555 it != backs.end(); ++it) {
2556 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2557 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2562 result = theConverters().getFlavor(path);
2565 // cache this flavor
2566 default_flavors_[dformat] = result;
2571 string BufferParams::getDefaultOutputFormat() const
2573 if (!default_output_format.empty()
2574 && default_output_format != "default")
2575 return default_output_format;
2577 || encoding().package() == Encoding::japanese) {
2578 FormatList const & formats = exportableFormats(true);
2579 if (formats.empty())
2581 // return the first we find
2582 return formats.front()->name();
2585 return lyxrc.default_otf_view_format;
2586 return lyxrc.default_view_format;
2589 Font const BufferParams::getFont() const
2591 FontInfo f = documentClass().defaultfont();
2592 if (fonts_default_family == "rmdefault")
2593 f.setFamily(ROMAN_FAMILY);
2594 else if (fonts_default_family == "sfdefault")
2595 f.setFamily(SANS_FAMILY);
2596 else if (fonts_default_family == "ttdefault")
2597 f.setFamily(TYPEWRITER_FAMILY);
2598 return Font(f, language);
2602 InsetQuotesParams::QuoteStyle BufferParams::getQuoteStyle(string const & qs) const
2604 return quotesstyletranslator().find(qs);
2608 bool BufferParams::isLatex() const
2610 return documentClass().outputType() == LATEX;
2614 bool BufferParams::isLiterate() const
2616 return documentClass().outputType() == LITERATE;
2620 bool BufferParams::isDocBook() const
2622 return documentClass().outputType() == DOCBOOK;
2626 void BufferParams::readPreamble(Lexer & lex)
2628 if (lex.getString() != "\\begin_preamble")
2629 lyxerr << "Error (BufferParams::readPreamble):"
2630 "consistency check failed." << endl;
2632 preamble = lex.getLongString(from_ascii("\\end_preamble"));
2636 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2638 string const expected = forced ? "\\begin_forced_local_layout" :
2639 "\\begin_local_layout";
2640 if (lex.getString() != expected)
2641 lyxerr << "Error (BufferParams::readLocalLayout):"
2642 "consistency check failed." << endl;
2645 forced_local_layout_ =
2646 lex.getLongString(from_ascii("\\end_forced_local_layout"));
2648 local_layout_ = lex.getLongString(from_ascii("\\end_local_layout"));
2652 bool BufferParams::setLanguage(string const & lang)
2654 Language const *new_language = languages.getLanguage(lang);
2655 if (!new_language) {
2656 // Language lang was not found
2659 language = new_language;
2664 void BufferParams::readLanguage(Lexer & lex)
2666 if (!lex.next()) return;
2668 string const tmptok = lex.getString();
2670 // check if tmptok is part of tex_babel in tex-defs.h
2671 if (!setLanguage(tmptok)) {
2672 // Language tmptok was not found
2673 language = default_language;
2674 lyxerr << "Warning: Setting language `"
2675 << tmptok << "' to `" << language->lang()
2681 void BufferParams::readGraphicsDriver(Lexer & lex)
2686 string const tmptok = lex.getString();
2687 // check if tmptok is part of tex_graphics in tex_defs.h
2690 string const test = tex_graphics[n++];
2692 if (test == tmptok) {
2693 graphics_driver = tmptok;
2698 "Warning: graphics driver `$$Token' not recognized!\n"
2699 " Setting graphics driver to `default'.\n");
2700 graphics_driver = "default";
2707 void BufferParams::readBullets(Lexer & lex)
2712 int const index = lex.getInteger();
2714 int temp_int = lex.getInteger();
2715 user_defined_bullet(index).setFont(temp_int);
2716 temp_bullet(index).setFont(temp_int);
2718 user_defined_bullet(index).setCharacter(temp_int);
2719 temp_bullet(index).setCharacter(temp_int);
2721 user_defined_bullet(index).setSize(temp_int);
2722 temp_bullet(index).setSize(temp_int);
2726 void BufferParams::readBulletsLaTeX(Lexer & lex)
2728 // The bullet class should be able to read this.
2731 int const index = lex.getInteger();
2733 docstring const temp_str = lex.getDocString();
2735 user_defined_bullet(index).setText(temp_str);
2736 temp_bullet(index).setText(temp_str);
2740 void BufferParams::readModules(Lexer & lex)
2742 if (!lex.eatLine()) {
2743 lyxerr << "Error (BufferParams::readModules):"
2744 "Unexpected end of input." << endl;
2748 string mod = lex.getString();
2749 if (mod == "\\end_modules")
2751 addLayoutModule(mod);
2757 void BufferParams::readRemovedModules(Lexer & lex)
2759 if (!lex.eatLine()) {
2760 lyxerr << "Error (BufferParams::readRemovedModules):"
2761 "Unexpected end of input." << endl;
2765 string mod = lex.getString();
2766 if (mod == "\\end_removed_modules")
2768 removed_modules_.push_back(mod);
2771 // now we want to remove any removed modules that were previously
2772 // added. normally, that will be because default modules were added in
2773 // setBaseClass(), which gets called when \textclass is read at the
2774 // start of the read.
2775 list<string>::const_iterator rit = removed_modules_.begin();
2776 list<string>::const_iterator const ren = removed_modules_.end();
2777 for (; rit != ren; ++rit) {
2778 LayoutModuleList::iterator const mit = layout_modules_.begin();
2779 LayoutModuleList::iterator const men = layout_modules_.end();
2780 LayoutModuleList::iterator found = find(mit, men, *rit);
2783 layout_modules_.erase(found);
2788 void BufferParams::readIncludeonly(Lexer & lex)
2790 if (!lex.eatLine()) {
2791 lyxerr << "Error (BufferParams::readIncludeonly):"
2792 "Unexpected end of input." << endl;
2796 string child = lex.getString();
2797 if (child == "\\end_includeonly")
2799 included_children_.push_back(child);
2805 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2807 switch (papersize) {
2809 // could be anything, so don't guess
2811 case PAPER_CUSTOM: {
2812 if (purpose == XDVI && !paperwidth.empty() &&
2813 !paperheight.empty()) {
2814 // heightxwidth<unit>
2815 string first = paperwidth;
2816 string second = paperheight;
2817 if (orientation == ORIENTATION_LANDSCAPE)
2820 return first.erase(first.length() - 2)
2826 // dvips and dvipdfm do not know this
2827 if (purpose == DVIPS || purpose == DVIPDFM)
2831 if (purpose == DVIPS || purpose == DVIPDFM)
2835 if (purpose == DVIPS || purpose == DVIPDFM)
2845 if (purpose == DVIPS || purpose == DVIPDFM)
2849 if (purpose == DVIPS || purpose == DVIPDFM)
2853 if (purpose == DVIPS || purpose == DVIPDFM)
2857 if (purpose == DVIPS || purpose == DVIPDFM)
2861 if (purpose == DVIPS || purpose == DVIPDFM)
2865 // dvipdfm does not know this
2866 if (purpose == DVIPDFM)
2870 if (purpose == DVIPDFM)
2874 if (purpose == DVIPS || purpose == DVIPDFM)
2878 if (purpose == DVIPS || purpose == DVIPDFM)
2882 if (purpose == DVIPS || purpose == DVIPDFM)
2886 if (purpose == DVIPS || purpose == DVIPDFM)
2890 if (purpose == DVIPS || purpose == DVIPDFM)
2894 if (purpose == DVIPS || purpose == DVIPDFM)
2898 if (purpose == DVIPS || purpose == DVIPDFM)
2902 if (purpose == DVIPS || purpose == DVIPDFM)
2906 if (purpose == DVIPS || purpose == DVIPDFM)
2910 if (purpose == DVIPS || purpose == DVIPDFM)
2914 if (purpose == DVIPS || purpose == DVIPDFM)
2918 if (purpose == DVIPS || purpose == DVIPDFM)
2922 if (purpose == DVIPS || purpose == DVIPDFM)
2926 if (purpose == DVIPS || purpose == DVIPDFM)
2930 if (purpose == DVIPS || purpose == DVIPDFM)
2933 case PAPER_USEXECUTIVE:
2934 // dvipdfm does not know this
2935 if (purpose == DVIPDFM)
2940 case PAPER_USLETTER:
2942 if (purpose == XDVI)
2949 string const BufferParams::dvips_options() const
2953 // If the class loads the geometry package, we do not know which
2954 // paper size is used, since we do not set it (bug 7013).
2955 // Therefore we must not specify any argument here.
2956 // dvips gets the correct paper size via DVI specials in this case
2957 // (if the class uses the geometry package correctly).
2958 if (documentClass().provides("geometry"))
2962 && papersize == PAPER_CUSTOM
2963 && !lyxrc.print_paper_dimension_flag.empty()
2964 && !paperwidth.empty()
2965 && !paperheight.empty()) {
2966 // using a custom papersize
2967 result = lyxrc.print_paper_dimension_flag;
2968 result += ' ' + paperwidth;
2969 result += ',' + paperheight;
2971 string const paper_option = paperSizeName(DVIPS);
2972 if (!paper_option.empty() && (paper_option != "letter" ||
2973 orientation != ORIENTATION_LANDSCAPE)) {
2974 // dvips won't accept -t letter -t landscape.
2975 // In all other cases, include the paper size
2977 result = lyxrc.print_paper_flag;
2978 result += ' ' + paper_option;
2981 if (orientation == ORIENTATION_LANDSCAPE &&
2982 papersize != PAPER_CUSTOM)
2983 result += ' ' + lyxrc.print_landscape_flag;
2988 string const BufferParams::font_encoding() const
2990 return font_encodings().empty() ? "default" : font_encodings().back();
2994 vector<string> const BufferParams::font_encodings() const
2996 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2998 vector<string> fontencs;
3000 // "default" means "no explicit font encoding"
3001 if (doc_fontenc != "default") {
3002 fontencs = getVectorFromString(doc_fontenc);
3003 if (!language->fontenc().empty()
3004 && ascii_lowercase(language->fontenc()) != "none") {
3005 vector<string> fencs = getVectorFromString(language->fontenc());
3006 vector<string>::const_iterator fit = fencs.begin();
3007 for (; fit != fencs.end(); ++fit) {
3008 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
3009 fontencs.push_back(*fit);
3018 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
3020 // suppress the babel call if there is no BabelName defined
3021 // for the document language in the lib/languages file and if no
3022 // other languages are used (lang_opts is then empty)
3023 if (lang_opts.empty())
3025 // either a specific language (AsBabelOptions setting in
3026 // lib/languages) or the prefs require the languages to
3027 // be submitted to babel itself (not the class).
3029 return "\\usepackage[" + lang_opts + "]{babel}";
3030 return "\\usepackage{babel}";
3034 docstring BufferParams::getGraphicsDriver(string const & package) const
3038 if (package == "geometry") {
3039 if (graphics_driver == "dvips"
3040 || graphics_driver == "dvipdfm"
3041 || graphics_driver == "pdftex"
3042 || graphics_driver == "vtex")
3043 result = from_ascii(graphics_driver);
3044 else if (graphics_driver == "dvipdfmx")
3045 result = from_ascii("dvipdfm");
3052 void BufferParams::writeEncodingPreamble(otexstream & os,
3053 LaTeXFeatures & features) const
3055 // XeTeX/LuaTeX: (see also #9740)
3056 // With Unicode fonts we use utf8-plain without encoding package.
3057 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
3058 // XeTeX must use ASCII encoding (see Buffer.cpp),
3059 // for LuaTeX, we load "luainputenc" (see below).
3060 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
3063 if (inputenc == "auto") {
3064 string const doc_encoding =
3065 language->encoding()->latexName();
3066 Encoding::Package const package =
3067 language->encoding()->package();
3069 // Create list of inputenc options:
3070 set<string> encodings;
3071 // luainputenc fails with more than one encoding
3072 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
3073 // list all input encodings used in the document
3074 encodings = features.getEncodingSet(doc_encoding);
3076 // If the "japanese" package (i.e. pLaTeX) is used,
3077 // inputenc must be omitted.
3078 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
3079 if ((!encodings.empty() || package == Encoding::inputenc)
3080 && !features.isRequired("japanese")
3081 && !features.isProvided("inputenc")) {
3082 os << "\\usepackage[";
3083 set<string>::const_iterator it = encodings.begin();
3084 set<string>::const_iterator const end = encodings.end();
3086 os << from_ascii(*it);
3089 for (; it != end; ++it)
3090 os << ',' << from_ascii(*it);
3091 if (package == Encoding::inputenc) {
3092 if (!encodings.empty())
3094 os << from_ascii(doc_encoding);
3096 if (features.runparams().flavor == OutputParams::LUATEX
3097 || features.runparams().flavor == OutputParams::DVILUATEX)
3098 os << "]{luainputenc}\n";
3100 os << "]{inputenc}\n";
3102 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3103 if (language->encoding()->name() == "utf8-cjk"
3104 && LaTeXFeatures::isAvailable("CJKutf8"))
3105 os << "\\usepackage{CJKutf8}\n";
3107 os << "\\usepackage{CJK}\n";
3109 } else if (inputenc != "default") {
3110 switch (encoding().package()) {
3111 case Encoding::none:
3112 case Encoding::japanese:
3114 case Encoding::inputenc:
3115 // do not load inputenc if japanese is used
3116 // or if the class provides inputenc
3117 if (features.isRequired("japanese")
3118 || features.isProvided("inputenc"))
3120 os << "\\usepackage[" << from_ascii(encoding().latexName());
3121 if (features.runparams().flavor == OutputParams::LUATEX
3122 || features.runparams().flavor == OutputParams::DVILUATEX)
3123 os << "]{luainputenc}\n";
3125 os << "]{inputenc}\n";
3128 if (encoding().name() == "utf8-cjk"
3129 && LaTeXFeatures::isAvailable("CJKutf8"))
3130 os << "\\usepackage{CJKutf8}\n";
3132 os << "\\usepackage{CJK}\n";
3135 // Load the CJK package if needed by a secondary language.
3136 // If the main encoding is some variant of UTF8, use CJKutf8.
3137 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3138 if (encoding().iconvName() == "UTF-8"
3139 && LaTeXFeatures::isAvailable("CJKutf8"))
3140 os << "\\usepackage{CJKutf8}\n";
3142 os << "\\usepackage{CJK}\n";
3148 string const BufferParams::parseFontName(string const & name) const
3150 string mangled = name;
3151 size_t const idx = mangled.find('[');
3152 if (idx == string::npos || idx == 0)
3155 return mangled.substr(0, idx - 1);
3159 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3161 if (fontsRoman() == "default" && fontsSans() == "default"
3162 && fontsTypewriter() == "default"
3163 && (fontsMath() == "default" || fontsMath() == "auto"))
3169 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3170 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3171 * Mapping=tex-text option assures TeX ligatures (such as "--")
3172 * are resolved. Note that tt does not use these ligatures.
3174 * -- add more GUI options?
3175 * -- add more fonts (fonts for other scripts)
3176 * -- if there's a way to find out if a font really supports
3177 * OldStyle, enable/disable the widget accordingly.
3179 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3180 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3181 // However, until v.2 (2010/07/11) fontspec only knew
3182 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3183 // was introduced for both XeTeX and LuaTeX (LuaTeX
3184 // didn't understand "Mapping=tex-text", while XeTeX
3185 // understood both. With most recent versions, both
3186 // variants are understood by both engines. However,
3187 // we want to provide support for at least TeXLive 2009
3188 // (for XeTeX; LuaTeX is only supported as of v.2)
3189 string const texmapping =
3190 (features.runparams().flavor == OutputParams::XETEX) ?
3191 "Mapping=tex-text" : "Ligatures=TeX";
3192 if (fontsRoman() != "default") {
3193 os << "\\setmainfont[" << texmapping;
3194 if (fonts_old_figures)
3195 os << ",Numbers=OldStyle";
3196 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3198 if (fontsSans() != "default") {
3199 string const sans = parseFontName(fontsSans());
3200 if (fontsSansScale() != 100)
3201 os << "\\setsansfont[Scale="
3202 << float(fontsSansScale()) / 100
3203 << "," << texmapping << "]{"
3206 os << "\\setsansfont[" << texmapping << "]{"
3209 if (fontsTypewriter() != "default") {
3210 string const mono = parseFontName(fontsTypewriter());
3211 if (fontsTypewriterScale() != 100)
3212 os << "\\setmonofont[Scale="
3213 << float(fontsTypewriterScale()) / 100
3217 os << "\\setmonofont{"
3224 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3225 bool const dryrun = features.runparams().dryrun;
3226 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3227 bool const nomath = (fontsMath() == "default");
3230 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3231 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3235 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3236 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3237 nomath, fontsSansScale());
3239 // MONOSPACED/TYPEWRITER
3240 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3241 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3242 nomath, fontsTypewriterScale());
3245 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3246 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3253 Encoding const & BufferParams::encoding() const
3255 // Main encoding for LaTeX output.
3257 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3258 // As the "flavor" is only known once export started, this
3259 // cannot be handled here. Instead, runparams.encoding is set
3260 // to ASCII in Buffer::makeLaTeXFile (for export)
3261 // and Buffer::writeLaTeXSource (for preview).
3263 return *(encodings.fromLyXName("utf8-plain"));
3264 if (inputenc == "auto" || inputenc == "default")
3265 return *language->encoding();
3266 Encoding const * const enc = encodings.fromLyXName(inputenc);
3269 LYXERR0("Unknown inputenc value `" << inputenc
3270 << "'. Using `auto' instead.");
3271 return *language->encoding();
3275 bool BufferParams::addCiteEngine(string const & engine)
3277 LayoutModuleList::const_iterator it = cite_engine_.begin();
3278 LayoutModuleList::const_iterator en = cite_engine_.end();
3279 for (; it != en; ++it)
3282 cite_engine_.push_back(engine);
3287 bool BufferParams::addCiteEngine(vector<string> const & engine)
3289 vector<string>::const_iterator it = engine.begin();
3290 vector<string>::const_iterator en = engine.end();
3292 for (; it != en; ++it)
3293 if (!addCiteEngine(*it))
3299 string const & BufferParams::defaultBiblioStyle() const
3301 map<string, string> bs = documentClass().defaultBiblioStyle();
3302 return bs[theCiteEnginesList.getTypeAsString(citeEngineType())];
3306 bool const & BufferParams::fullAuthorList() const
3308 return documentClass().fullAuthorList();
3312 string BufferParams::getCiteAlias(string const & s) const
3314 vector<string> commands =
3315 documentClass().citeCommands(citeEngineType());
3316 // If it is a real command, don't treat it as an alias
3317 if (find(commands.begin(), commands.end(), s) != commands.end())
3319 map<string,string> aliases = documentClass().citeCommandAliases();
3320 if (aliases.find(s) != aliases.end())
3326 void BufferParams::setCiteEngine(string const & engine)
3329 addCiteEngine(engine);
3333 void BufferParams::setCiteEngine(vector<string> const & engine)
3336 addCiteEngine(engine);
3340 vector<string> BufferParams::citeCommands() const
3342 static CitationStyle const default_style;
3343 vector<string> commands =
3344 documentClass().citeCommands(citeEngineType());
3345 if (commands.empty())
3346 commands.push_back(default_style.name);
3351 vector<CitationStyle> BufferParams::citeStyles() const
3353 static CitationStyle const default_style;
3354 vector<CitationStyle> styles =
3355 documentClass().citeStyles(citeEngineType());
3357 styles.push_back(default_style);
3362 string const BufferParams::bibtexCommand() const
3364 // Return document-specific setting if available
3365 if (bibtex_command != "default")
3366 return bibtex_command;
3368 // If we have "default" in document settings, consult the prefs
3369 // 1. Japanese (uses a specific processor)
3370 if (encoding().package() == Encoding::japanese) {
3371 if (lyxrc.jbibtex_command != "automatic")
3372 // Return the specified program, if "automatic" is not set
3373 return lyxrc.jbibtex_command;
3374 else if (!useBiblatex()) {
3375 // With classic BibTeX, return pbibtex, jbibtex, bibtex
3376 if (lyxrc.jbibtex_alternatives.find("pbibtex") != lyxrc.jbibtex_alternatives.end())
3378 if (lyxrc.jbibtex_alternatives.find("jbibtex") != lyxrc.jbibtex_alternatives.end())
3383 // 2. All other languages
3384 else if (lyxrc.bibtex_command != "automatic")
3385 // Return the specified program, if "automatic" is not set
3386 return lyxrc.bibtex_command;
3388 // 3. Automatic: find the most suitable for the current cite framework
3389 if (useBiblatex()) {
3390 // For Biblatex, we prefer biber (also for Japanese)
3391 // and fall back to bibtex8 and, as last resort, bibtex
3392 if (lyxrc.bibtex_alternatives.find("biber") != lyxrc.bibtex_alternatives.end())
3394 else if (lyxrc.bibtex_alternatives.find("bibtex8") != lyxrc.bibtex_alternatives.end())
3401 bool BufferParams::useBiblatex() const
3403 return theCiteEnginesList[citeEngine().list().front()]
3404 ->getCiteFramework() == "biblatex";
3408 void BufferParams::invalidateConverterCache() const
3410 pimpl_->isExportCacheValid = false;
3411 pimpl_->isViewCacheValid = false;