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 AuthorList & BufferParams::authors()
528 return pimpl_->authorlist;
532 AuthorList const & BufferParams::authors() const
534 return pimpl_->authorlist;
538 void BufferParams::addAuthor(Author a)
540 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
544 BranchList & BufferParams::branchlist()
546 return pimpl_->branchlist;
550 BranchList const & BufferParams::branchlist() const
552 return pimpl_->branchlist;
556 IndicesList & BufferParams::indiceslist()
558 return pimpl_->indiceslist;
562 IndicesList const & BufferParams::indiceslist() const
564 return pimpl_->indiceslist;
568 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
570 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
571 return pimpl_->temp_bullets[index];
575 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
577 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
578 return pimpl_->temp_bullets[index];
582 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
584 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
585 return pimpl_->user_defined_bullets[index];
589 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
591 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
592 return pimpl_->user_defined_bullets[index];
596 Spacing & BufferParams::spacing()
598 return pimpl_->spacing;
602 Spacing const & BufferParams::spacing() const
604 return pimpl_->spacing;
608 PDFOptions & BufferParams::pdfoptions()
610 return pimpl_->pdfoptions;
614 PDFOptions const & BufferParams::pdfoptions() const
616 return pimpl_->pdfoptions;
620 HSpace const & BufferParams::getIndentation() const
622 return pimpl_->indentation;
626 void BufferParams::setIndentation(HSpace const & indent)
628 pimpl_->indentation = indent;
632 VSpace const & BufferParams::getDefSkip() const
634 return pimpl_->defskip;
638 void BufferParams::setDefSkip(VSpace const & vs)
640 // DEFSKIP will cause an infinite loop
641 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
642 pimpl_->defskip = vs;
646 string BufferParams::readToken(Lexer & lex, string const & token,
647 FileName const & filepath)
651 if (token == "\\textclass") {
653 string const classname = lex.getString();
654 // if there exists a local layout file, ignore the system one
655 // NOTE: in this case, the textclass (.cls file) is assumed to
658 LayoutFileList & bcl = LayoutFileList::get();
659 if (!filepath.empty()) {
660 // If classname is an absolute path, the document is
661 // using a local layout file which could not be accessed
662 // by a relative path. In this case the path is correct
663 // even if the document was moved to a different
664 // location. However, we will have a problem if the
665 // document was generated on a different platform.
666 bool isabsolute = FileName::isAbsolute(classname);
667 string const classpath = onlyPath(classname);
668 string const path = isabsolute ? classpath
669 : FileName(addPath(filepath.absFileName(),
670 classpath)).realPath();
671 string const oldpath = isabsolute ? string()
672 : FileName(addPath(origin, classpath)).realPath();
673 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
675 // that returns non-empty if a "local" layout file is found.
677 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
678 from_utf8(filepath.absFileName())));
681 setBaseClass(onlyFileName(tcp));
683 setBaseClass(onlyFileName(classname));
684 // We assume that a tex class exists for local or unknown
685 // layouts so this warning, will only be given for system layouts.
686 if (!baseClass()->isTeXClassAvailable()) {
687 docstring const desc =
688 translateIfPossible(from_utf8(baseClass()->description()));
689 docstring const prereqs =
690 from_utf8(baseClass()->prerequisites());
691 docstring const msg =
692 bformat(_("The selected document class\n"
694 "requires external files that are not available.\n"
695 "The document class can still be used, but the\n"
696 "document cannot be compiled until the following\n"
697 "prerequisites are installed:\n"
699 "See section 3.1.2.2 (Class Availability) of the\n"
700 "User's Guide for more information."), desc, prereqs);
701 frontend::Alert::warning(_("Document class not available"),
704 } else if (token == "\\save_transient_properties") {
705 lex >> save_transient_properties;
706 } else if (token == "\\origin") {
708 origin = lex.getString();
709 string const sysdirprefix = "/systemlyxdir/";
710 if (prefixIs(origin, sysdirprefix)) {
712 if (inSystemDir(filepath, docsys))
713 origin.replace(0, sysdirprefix.length() - 1, docsys);
715 origin.replace(0, sysdirprefix.length() - 1,
716 package().system_support().absFileName());
718 } else if (token == "\\begin_preamble") {
720 } else if (token == "\\begin_local_layout") {
721 readLocalLayout(lex, false);
722 } else if (token == "\\begin_forced_local_layout") {
723 readLocalLayout(lex, true);
724 } else if (token == "\\begin_modules") {
726 } else if (token == "\\begin_removed_modules") {
727 readRemovedModules(lex);
728 } else if (token == "\\begin_includeonly") {
729 readIncludeonly(lex);
730 } else if (token == "\\maintain_unincluded_children") {
731 lex >> maintain_unincluded_children;
732 } else if (token == "\\options") {
734 options = lex.getString();
735 } else if (token == "\\use_default_options") {
736 lex >> use_default_options;
737 } else if (token == "\\master") {
739 master = lex.getString();
740 if (!filepath.empty() && FileName::isAbsolute(origin)) {
741 bool const isabs = FileName::isAbsolute(master);
742 FileName const abspath(isabs ? master : origin + master);
743 bool const moved = filepath != FileName(origin);
744 if (moved && abspath.exists()) {
745 docstring const path = isabs
747 : from_utf8(abspath.realPath());
748 docstring const refpath =
749 from_utf8(filepath.absFileName());
750 master = to_utf8(makeRelPath(path, refpath));
753 } else if (token == "\\suppress_date") {
754 lex >> suppress_date;
755 } else if (token == "\\justification") {
756 lex >> justification;
757 } else if (token == "\\language") {
759 } else if (token == "\\language_package") {
761 lang_package = lex.getString();
762 } else if (token == "\\inputencoding") {
764 } else if (token == "\\graphics") {
765 readGraphicsDriver(lex);
766 } else if (token == "\\default_output_format") {
767 lex >> default_output_format;
768 } else if (token == "\\bibtex_command") {
770 bibtex_command = lex.getString();
771 } else if (token == "\\index_command") {
773 index_command = lex.getString();
774 } else if (token == "\\fontencoding") {
776 fontenc = lex.getString();
777 } else if (token == "\\font_roman") {
778 lex >> fonts_roman[0];
779 lex >> fonts_roman[1];
780 } else if (token == "\\font_sans") {
781 lex >> fonts_sans[0];
782 lex >> fonts_sans[1];
783 } else if (token == "\\font_typewriter") {
784 lex >> fonts_typewriter[0];
785 lex >> fonts_typewriter[1];
786 } else if (token == "\\font_math") {
787 lex >> fonts_math[0];
788 lex >> fonts_math[1];
789 } else if (token == "\\font_default_family") {
790 lex >> fonts_default_family;
791 } else if (token == "\\use_non_tex_fonts") {
792 lex >> useNonTeXFonts;
793 } else if (token == "\\font_sc") {
794 lex >> fonts_expert_sc;
795 } else if (token == "\\font_osf") {
796 lex >> fonts_old_figures;
797 } else if (token == "\\font_sf_scale") {
798 lex >> fonts_sans_scale[0];
799 lex >> fonts_sans_scale[1];
800 } else if (token == "\\font_tt_scale") {
801 lex >> fonts_typewriter_scale[0];
802 lex >> fonts_typewriter_scale[1];
803 } else if (token == "\\font_cjk") {
805 } else if (token == "\\use_microtype") {
806 lex >> use_microtype;
807 } else if (token == "\\paragraph_separation") {
810 paragraph_separation = parseptranslator().find(parsep);
811 } else if (token == "\\paragraph_indentation") {
813 string indentation = lex.getString();
814 pimpl_->indentation = HSpace(indentation);
815 } else if (token == "\\defskip") {
817 string const defskip = lex.getString();
818 pimpl_->defskip = VSpace(defskip);
819 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
821 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
822 } else if (token == "\\quotes_style") {
825 quotes_style = quotesstyletranslator().find(qstyle);
826 } else if (token == "\\dynamic_quotes") {
827 lex >> dynamic_quotes;
828 } else if (token == "\\papersize") {
831 papersize = papersizetranslator().find(ppsize);
832 } else if (token == "\\use_geometry") {
834 } else if (token == "\\use_package") {
839 use_package(package, packagetranslator().find(use));
840 } else if (token == "\\cite_engine") {
842 vector<string> engine = getVectorFromString(lex.getString());
843 setCiteEngine(engine);
844 } else if (token == "\\cite_engine_type") {
847 cite_engine_type_ = theCiteEnginesList.getType(engine_type);
848 } else if (token == "\\biblio_style") {
850 biblio_style = lex.getString();
851 } else if (token == "\\biblio_options") {
853 biblio_opts = trim(lex.getString());
854 } else if (token == "\\biblatex_bibstyle") {
856 biblatex_bibstyle = trim(lex.getString());
857 } else if (token == "\\biblatex_citestyle") {
859 biblatex_citestyle = trim(lex.getString());
860 } else if (token == "\\use_bibtopic") {
862 } else if (token == "\\multibib") {
864 } else if (token == "\\use_indices") {
866 } else if (token == "\\tracking_changes") {
867 lex >> track_changes;
868 } else if (token == "\\output_changes") {
869 lex >> output_changes;
870 } else if (token == "\\branch") {
872 docstring branch = lex.getDocString();
873 branchlist().add(branch);
876 string const tok = lex.getString();
877 if (tok == "\\end_branch")
879 Branch * branch_ptr = branchlist().find(branch);
880 if (tok == "\\selected") {
883 branch_ptr->setSelected(lex.getInteger());
885 if (tok == "\\filename_suffix") {
888 branch_ptr->setFileNameSuffix(lex.getInteger());
890 if (tok == "\\color") {
892 string color = lex.getString();
894 branch_ptr->setColor(color);
895 // Update also the Color table:
897 color = lcolor.getX11Name(Color_background);
899 lcolor.setColor(to_utf8(branch), color);
902 } else if (token == "\\index") {
904 docstring index = lex.getDocString();
906 indiceslist().add(index);
909 string const tok = lex.getString();
910 if (tok == "\\end_index")
912 Index * index_ptr = indiceslist().find(index);
913 if (tok == "\\shortcut") {
915 shortcut = lex.getDocString();
917 index_ptr->setShortcut(shortcut);
919 if (tok == "\\color") {
921 string color = lex.getString();
923 index_ptr->setColor(color);
924 // Update also the Color table:
926 color = lcolor.getX11Name(Color_background);
928 if (!shortcut.empty())
929 lcolor.setColor(to_utf8(shortcut), color);
932 } else if (token == "\\author") {
934 istringstream ss(lex.getString());
938 } else if (token == "\\paperorientation") {
941 orientation = paperorientationtranslator().find(orient);
942 } else if (token == "\\backgroundcolor") {
944 backgroundcolor = lyx::rgbFromHexName(lex.getString());
945 isbackgroundcolor = true;
946 } else if (token == "\\fontcolor") {
948 fontcolor = lyx::rgbFromHexName(lex.getString());
950 } else if (token == "\\notefontcolor") {
952 string color = lex.getString();
953 notefontcolor = lyx::rgbFromHexName(color);
954 lcolor.setColor("notefontcolor", color);
955 } else if (token == "\\boxbgcolor") {
957 string color = lex.getString();
958 boxbgcolor = lyx::rgbFromHexName(color);
959 lcolor.setColor("boxbgcolor", color);
960 } else if (token == "\\paperwidth") {
962 } else if (token == "\\paperheight") {
964 } else if (token == "\\leftmargin") {
966 } else if (token == "\\topmargin") {
968 } else if (token == "\\rightmargin") {
970 } else if (token == "\\bottommargin") {
972 } else if (token == "\\headheight") {
974 } else if (token == "\\headsep") {
976 } else if (token == "\\footskip") {
978 } else if (token == "\\columnsep") {
980 } else if (token == "\\paperfontsize") {
982 } else if (token == "\\papercolumns") {
984 } else if (token == "\\listings_params") {
987 listings_params = InsetListingsParams(par).params();
988 } else if (token == "\\papersides") {
991 sides = sidestranslator().find(psides);
992 } else if (token == "\\paperpagestyle") {
994 } else if (token == "\\bullet") {
996 } else if (token == "\\bulletLaTeX") {
997 readBulletsLaTeX(lex);
998 } else if (token == "\\secnumdepth") {
1000 } else if (token == "\\tocdepth") {
1002 } else if (token == "\\spacing") {
1006 if (nspacing == "other") {
1009 spacing().set(spacetranslator().find(nspacing), tmp_val);
1010 } else if (token == "\\float_placement") {
1011 lex >> float_placement;
1013 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
1014 string toktmp = pdfoptions().readToken(lex, token);
1015 if (!toktmp.empty()) {
1016 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
1020 } else if (token == "\\html_math_output") {
1023 html_math_output = static_cast<MathOutput>(temp);
1024 } else if (token == "\\html_be_strict") {
1025 lex >> html_be_strict;
1026 } else if (token == "\\html_css_as_file") {
1027 lex >> html_css_as_file;
1028 } else if (token == "\\html_math_img_scale") {
1029 lex >> html_math_img_scale;
1030 } else if (token == "\\html_latex_start") {
1032 html_latex_start = lex.getString();
1033 } else if (token == "\\html_latex_end") {
1035 html_latex_end = lex.getString();
1036 } else if (token == "\\output_sync") {
1038 } else if (token == "\\output_sync_macro") {
1039 lex >> output_sync_macro;
1040 } else if (token == "\\use_refstyle") {
1041 lex >> use_refstyle;
1043 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1053 // Quote argument if it contains spaces
1054 string quoteIfNeeded(string const & str) {
1055 if (contains(str, ' '))
1056 return "\"" + str + "\"";
1062 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1064 // The top of the file is written by the buffer.
1065 // Prints out the buffer info into the .lyx file given by file
1067 os << "\\save_transient_properties "
1068 << convert<string>(save_transient_properties) << '\n';
1070 // the document directory (must end with a path separator)
1071 // realPath() is used to resolve symlinks, while addPath(..., "")
1072 // ensures a trailing path separator.
1074 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1075 string const sysdir = inSystemDir(FileName(filepath), docsys) ? docsys
1076 : addPath(package().system_support().realPath(), "");
1077 string const relpath =
1078 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1079 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1080 filepath = addPath("/systemlyxdir", relpath);
1081 else if (!save_transient_properties || !lyxrc.save_origin)
1082 filepath = "unavailable";
1083 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1086 os << "\\textclass "
1087 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1088 baseClass()->name()), "layout"))
1091 // then the preamble
1092 if (!preamble.empty()) {
1093 // remove '\n' from the end of preamble
1094 docstring const tmppreamble = rtrim(preamble, "\n");
1095 os << "\\begin_preamble\n"
1096 << to_utf8(tmppreamble)
1097 << "\n\\end_preamble\n";
1101 if (!options.empty()) {
1102 os << "\\options " << options << '\n';
1105 // use the class options defined in the layout?
1106 os << "\\use_default_options "
1107 << convert<string>(use_default_options) << "\n";
1109 // the master document
1110 if (!master.empty()) {
1111 os << "\\master " << master << '\n';
1115 if (!removed_modules_.empty()) {
1116 os << "\\begin_removed_modules" << '\n';
1117 list<string>::const_iterator it = removed_modules_.begin();
1118 list<string>::const_iterator en = removed_modules_.end();
1119 for (; it != en; ++it)
1121 os << "\\end_removed_modules" << '\n';
1125 if (!layout_modules_.empty()) {
1126 os << "\\begin_modules" << '\n';
1127 LayoutModuleList::const_iterator it = layout_modules_.begin();
1128 LayoutModuleList::const_iterator en = layout_modules_.end();
1129 for (; it != en; ++it)
1131 os << "\\end_modules" << '\n';
1135 if (!included_children_.empty()) {
1136 os << "\\begin_includeonly" << '\n';
1137 list<string>::const_iterator it = included_children_.begin();
1138 list<string>::const_iterator en = included_children_.end();
1139 for (; it != en; ++it)
1141 os << "\\end_includeonly" << '\n';
1143 os << "\\maintain_unincluded_children "
1144 << convert<string>(maintain_unincluded_children) << '\n';
1146 // local layout information
1147 docstring const local_layout = getLocalLayout(false);
1148 if (!local_layout.empty()) {
1149 // remove '\n' from the end
1150 docstring const tmplocal = rtrim(local_layout, "\n");
1151 os << "\\begin_local_layout\n"
1152 << to_utf8(tmplocal)
1153 << "\n\\end_local_layout\n";
1155 docstring const forced_local_layout = getLocalLayout(true);
1156 if (!forced_local_layout.empty()) {
1157 // remove '\n' from the end
1158 docstring const tmplocal = rtrim(forced_local_layout, "\n");
1159 os << "\\begin_forced_local_layout\n"
1160 << to_utf8(tmplocal)
1161 << "\n\\end_forced_local_layout\n";
1164 // then the text parameters
1165 if (language != ignore_language)
1166 os << "\\language " << language->lang() << '\n';
1167 os << "\\language_package " << lang_package
1168 << "\n\\inputencoding " << inputenc
1169 << "\n\\fontencoding " << fontenc
1170 << "\n\\font_roman \"" << fonts_roman[0]
1171 << "\" \"" << fonts_roman[1] << '"'
1172 << "\n\\font_sans \"" << fonts_sans[0]
1173 << "\" \"" << fonts_sans[1] << '"'
1174 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1175 << "\" \"" << fonts_typewriter[1] << '"'
1176 << "\n\\font_math \"" << fonts_math[0]
1177 << "\" \"" << fonts_math[1] << '"'
1178 << "\n\\font_default_family " << fonts_default_family
1179 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1180 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1181 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1182 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1183 << ' ' << fonts_sans_scale[1]
1184 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1185 << ' ' << fonts_typewriter_scale[1]
1187 if (!fonts_cjk.empty()) {
1188 os << "\\font_cjk " << fonts_cjk << '\n';
1190 os << "\\use_microtype " << convert<string>(use_microtype) << '\n';
1191 os << "\\graphics " << graphics_driver << '\n';
1192 os << "\\default_output_format " << default_output_format << '\n';
1193 os << "\\output_sync " << output_sync << '\n';
1194 if (!output_sync_macro.empty())
1195 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1196 os << "\\bibtex_command " << bibtex_command << '\n';
1197 os << "\\index_command " << index_command << '\n';
1199 if (!float_placement.empty()) {
1200 os << "\\float_placement " << float_placement << '\n';
1202 os << "\\paperfontsize " << fontsize << '\n';
1204 spacing().writeFile(os);
1205 pdfoptions().writeFile(os);
1207 os << "\\papersize " << string_papersize[papersize]
1208 << "\n\\use_geometry " << convert<string>(use_geometry);
1209 map<string, string> const & packages = auto_packages();
1210 for (map<string, string>::const_iterator it = packages.begin();
1211 it != packages.end(); ++it)
1212 os << "\n\\use_package " << it->first << ' '
1213 << use_package(it->first);
1215 os << "\n\\cite_engine ";
1217 if (!cite_engine_.empty()) {
1218 LayoutModuleList::const_iterator be = cite_engine_.begin();
1219 LayoutModuleList::const_iterator en = cite_engine_.end();
1220 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1229 os << "\n\\cite_engine_type " << theCiteEnginesList.getTypeAsString(cite_engine_type_);
1231 if (!biblio_style.empty())
1232 os << "\n\\biblio_style " << biblio_style;
1233 if (!biblio_opts.empty())
1234 os << "\n\\biblio_options " << biblio_opts;
1235 if (!biblatex_bibstyle.empty())
1236 os << "\n\\biblatex_bibstyle " << biblatex_bibstyle;
1237 if (!biblatex_citestyle.empty())
1238 os << "\n\\biblatex_citestyle " << biblatex_citestyle;
1239 if (!multibib.empty())
1240 os << "\n\\multibib " << multibib;
1242 os << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1243 << "\n\\use_indices " << convert<string>(use_indices)
1244 << "\n\\paperorientation " << string_orientation[orientation]
1245 << "\n\\suppress_date " << convert<string>(suppress_date)
1246 << "\n\\justification " << convert<string>(justification)
1247 << "\n\\use_refstyle " << use_refstyle
1249 if (isbackgroundcolor == true)
1250 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1251 if (isfontcolor == true)
1252 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1253 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1254 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1255 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1256 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1258 BranchList::const_iterator it = branchlist().begin();
1259 BranchList::const_iterator end = branchlist().end();
1260 for (; it != end; ++it) {
1261 os << "\\branch " << to_utf8(it->branch())
1262 << "\n\\selected " << it->isSelected()
1263 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1264 << "\n\\color " << lyx::X11hexname(it->color())
1269 IndicesList::const_iterator iit = indiceslist().begin();
1270 IndicesList::const_iterator iend = indiceslist().end();
1271 for (; iit != iend; ++iit) {
1272 os << "\\index " << to_utf8(iit->index())
1273 << "\n\\shortcut " << to_utf8(iit->shortcut())
1274 << "\n\\color " << lyx::X11hexname(iit->color())
1279 if (!paperwidth.empty())
1280 os << "\\paperwidth "
1281 << VSpace(paperwidth).asLyXCommand() << '\n';
1282 if (!paperheight.empty())
1283 os << "\\paperheight "
1284 << VSpace(paperheight).asLyXCommand() << '\n';
1285 if (!leftmargin.empty())
1286 os << "\\leftmargin "
1287 << VSpace(leftmargin).asLyXCommand() << '\n';
1288 if (!topmargin.empty())
1289 os << "\\topmargin "
1290 << VSpace(topmargin).asLyXCommand() << '\n';
1291 if (!rightmargin.empty())
1292 os << "\\rightmargin "
1293 << VSpace(rightmargin).asLyXCommand() << '\n';
1294 if (!bottommargin.empty())
1295 os << "\\bottommargin "
1296 << VSpace(bottommargin).asLyXCommand() << '\n';
1297 if (!headheight.empty())
1298 os << "\\headheight "
1299 << VSpace(headheight).asLyXCommand() << '\n';
1300 if (!headsep.empty())
1302 << VSpace(headsep).asLyXCommand() << '\n';
1303 if (!footskip.empty())
1305 << VSpace(footskip).asLyXCommand() << '\n';
1306 if (!columnsep.empty())
1307 os << "\\columnsep "
1308 << VSpace(columnsep).asLyXCommand() << '\n';
1309 os << "\\secnumdepth " << secnumdepth
1310 << "\n\\tocdepth " << tocdepth
1311 << "\n\\paragraph_separation "
1312 << string_paragraph_separation[paragraph_separation];
1313 if (!paragraph_separation)
1314 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1316 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1317 os << "\n\\quotes_style "
1318 << string_quotes_style[quotes_style]
1319 << "\n\\dynamic_quotes " << dynamic_quotes
1320 << "\n\\papercolumns " << columns
1321 << "\n\\papersides " << sides
1322 << "\n\\paperpagestyle " << pagestyle << '\n';
1323 if (!listings_params.empty())
1324 os << "\\listings_params \"" <<
1325 InsetListingsParams(listings_params).encodedString() << "\"\n";
1326 for (int i = 0; i < 4; ++i) {
1327 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1328 if (user_defined_bullet(i).getFont() != -1) {
1329 os << "\\bullet " << i << " "
1330 << user_defined_bullet(i).getFont() << " "
1331 << user_defined_bullet(i).getCharacter() << " "
1332 << user_defined_bullet(i).getSize() << "\n";
1336 os << "\\bulletLaTeX " << i << " \""
1337 << lyx::to_ascii(user_defined_bullet(i).getText())
1343 os << "\\tracking_changes "
1344 << (save_transient_properties ? convert<string>(track_changes) : "false")
1347 os << "\\output_changes "
1348 << (save_transient_properties ? convert<string>(output_changes) : "false")
1351 os << "\\html_math_output " << html_math_output << '\n'
1352 << "\\html_css_as_file " << html_css_as_file << '\n'
1353 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1355 if (html_math_img_scale != 1.0)
1356 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1357 if (!html_latex_start.empty())
1358 os << "\\html_latex_start " << html_latex_start << '\n';
1359 if (!html_latex_end.empty())
1360 os << "\\html_latex_end " << html_latex_end << '\n';
1362 os << pimpl_->authorlist;
1366 void BufferParams::validate(LaTeXFeatures & features) const
1368 features.require(documentClass().requires());
1370 if (columns > 1 && language->rightToLeft())
1371 features.require("rtloutputdblcol");
1373 if (output_changes) {
1374 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1375 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1376 LaTeXFeatures::isAvailable("xcolor");
1378 switch (features.runparams().flavor) {
1379 case OutputParams::LATEX:
1380 case OutputParams::DVILUATEX:
1382 features.require("ct-dvipost");
1383 features.require("dvipost");
1384 } else if (xcolorulem) {
1385 features.require("ct-xcolor-ulem");
1386 features.require("ulem");
1387 features.require("xcolor");
1389 features.require("ct-none");
1392 case OutputParams::LUATEX:
1393 case OutputParams::PDFLATEX:
1394 case OutputParams::XETEX:
1396 features.require("ct-xcolor-ulem");
1397 features.require("ulem");
1398 features.require("xcolor");
1399 // improves color handling in PDF output
1400 features.require("pdfcolmk");
1402 features.require("ct-none");
1410 // Floats with 'Here definitely' as default setting.
1411 if (float_placement.find('H') != string::npos)
1412 features.require("float");
1414 for (PackageMap::const_iterator it = use_packages.begin();
1415 it != use_packages.end(); ++it) {
1416 if (it->first == "amsmath") {
1417 // AMS Style is at document level
1418 if (it->second == package_on ||
1419 features.isProvided("amsmath"))
1420 features.require(it->first);
1421 } else if (it->second == package_on)
1422 features.require(it->first);
1425 // Document-level line spacing
1426 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1427 features.require("setspace");
1429 // the bullet shapes are buffer level not paragraph level
1430 // so they are tested here
1431 for (int i = 0; i < 4; ++i) {
1432 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1434 int const font = user_defined_bullet(i).getFont();
1436 int const c = user_defined_bullet(i).getCharacter();
1442 features.require("latexsym");
1444 } else if (font == 1) {
1445 features.require("amssymb");
1446 } else if (font >= 2 && font <= 5) {
1447 features.require("pifont");
1451 if (pdfoptions().use_hyperref) {
1452 features.require("hyperref");
1453 // due to interferences with babel and hyperref, the color package has to
1454 // be loaded after hyperref when hyperref is used with the colorlinks
1455 // option, see http://www.lyx.org/trac/ticket/5291
1456 if (pdfoptions().colorlinks)
1457 features.require("color");
1459 if (!listings_params.empty()) {
1460 // do not test validity because listings_params is
1461 // supposed to be valid
1463 InsetListingsParams(listings_params).separatedParams(true);
1464 // we can't support all packages, but we should load the color package
1465 if (par.find("\\color", 0) != string::npos)
1466 features.require("color");
1469 // some languages are only available via polyglossia
1470 if (features.hasPolyglossiaExclusiveLanguages())
1471 features.require("polyglossia");
1473 if (useNonTeXFonts && fontsMath() != "auto")
1474 features.require("unicode-math");
1477 features.require("microtype");
1479 if (!language->requires().empty())
1480 features.require(language->requires());
1484 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1485 FileName const & filepath) const
1487 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1488 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1489 // \RequirePackage to do so, rather than the normal \usepackage
1490 // Do not try to load any other package before the document class, unless you
1491 // have a thorough understanding of the LATEX internals and know exactly what you
1493 if (features.mustProvide("fix-cm"))
1494 os << "\\RequirePackage{fix-cm}\n";
1495 // Likewise for fixltx2e. If other packages conflict with this policy,
1496 // treat it as a package bug (and report it!)
1497 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1498 if (features.mustProvide("fixltx2e"))
1499 os << "\\RequirePackage{fixltx2e}\n";
1501 os << "\\documentclass";
1503 DocumentClass const & tclass = documentClass();
1505 ostringstream clsoptions; // the document class options.
1507 if (tokenPos(tclass.opt_fontsize(),
1508 '|', fontsize) >= 0) {
1509 // only write if existing in list (and not default)
1510 clsoptions << fontsize << "pt,";
1513 // all paper sizes except of A4, A5, B5 and the US sizes need the
1515 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1516 && papersize != PAPER_USLETTER
1517 && papersize != PAPER_USLEGAL
1518 && papersize != PAPER_USEXECUTIVE
1519 && papersize != PAPER_A4
1520 && papersize != PAPER_A5
1521 && papersize != PAPER_B5;
1523 if (!use_geometry) {
1524 switch (papersize) {
1526 clsoptions << "a4paper,";
1528 case PAPER_USLETTER:
1529 clsoptions << "letterpaper,";
1532 clsoptions << "a5paper,";
1535 clsoptions << "b5paper,";
1537 case PAPER_USEXECUTIVE:
1538 clsoptions << "executivepaper,";
1541 clsoptions << "legalpaper,";
1575 if (sides != tclass.sides()) {
1578 clsoptions << "oneside,";
1581 clsoptions << "twoside,";
1587 if (columns != tclass.columns()) {
1589 clsoptions << "twocolumn,";
1591 clsoptions << "onecolumn,";
1595 && orientation == ORIENTATION_LANDSCAPE)
1596 clsoptions << "landscape,";
1598 // language should be a parameter to \documentclass
1599 if (language->babel() == "hebrew"
1600 && default_language->babel() != "hebrew")
1601 // This seems necessary
1602 features.useLanguage(default_language);
1604 ostringstream language_options;
1605 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1606 bool const use_polyglossia = features.usePolyglossia();
1607 bool const global = lyxrc.language_global_options;
1608 if (use_babel || (use_polyglossia && global)) {
1609 language_options << features.getBabelLanguages();
1610 if (!language->babel().empty()) {
1611 if (!language_options.str().empty())
1612 language_options << ',';
1613 language_options << language->babel();
1615 if (global && !features.needBabelLangOptions()
1616 && !language_options.str().empty())
1617 clsoptions << language_options.str() << ',';
1620 // the predefined options from the layout
1621 if (use_default_options && !tclass.options().empty())
1622 clsoptions << tclass.options() << ',';
1624 // the user-defined options
1625 if (!options.empty()) {
1626 clsoptions << options << ',';
1629 string strOptions(clsoptions.str());
1630 if (!strOptions.empty()) {
1631 strOptions = rtrim(strOptions, ",");
1633 os << '[' << from_utf8(strOptions) << ']';
1636 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1637 // end of \documentclass defs
1639 // if we use fontspec or newtxmath, we have to load the AMS packages here
1640 string const ams = features.loadAMSPackages();
1641 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1642 bool const use_newtxmath =
1643 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1644 ot1, false, false) == "newtxmath";
1645 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1646 os << from_ascii(ams);
1648 if (useNonTeXFonts) {
1649 if (!features.isProvided("fontspec"))
1650 os << "\\usepackage{fontspec}\n";
1651 if (features.mustProvide("unicode-math")
1652 && features.isAvailable("unicode-math"))
1653 os << "\\usepackage{unicode-math}\n";
1656 // font selection must be done before loading fontenc.sty
1657 string const fonts = loadFonts(features);
1659 os << from_utf8(fonts);
1661 if (fonts_default_family != "default")
1662 os << "\\renewcommand{\\familydefault}{\\"
1663 << from_ascii(fonts_default_family) << "}\n";
1665 // set font encoding
1666 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1667 if (!useNonTeXFonts && !features.isProvided("fontenc")
1668 && font_encoding() != "default") {
1669 // get main font encodings
1670 vector<string> fontencs = font_encodings();
1671 // get font encodings of secondary languages
1672 features.getFontEncodings(fontencs);
1673 if (!fontencs.empty()) {
1674 os << "\\usepackage["
1675 << from_ascii(getStringFromVector(fontencs))
1680 // handle inputenc etc.
1681 writeEncodingPreamble(os, features);
1684 if (!features.runparams().includeall && !included_children_.empty()) {
1685 os << "\\includeonly{";
1686 list<string>::const_iterator it = included_children_.begin();
1687 list<string>::const_iterator en = included_children_.end();
1689 for (; it != en; ++it) {
1690 string incfile = *it;
1691 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1692 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1694 if (!features.runparams().nice)
1696 // \includeonly doesn't want an extension
1697 incfile = changeExtension(incfile, string());
1698 incfile = support::latex_path(incfile);
1699 if (!incfile.empty()) {
1702 os << from_utf8(incfile);
1709 if (!features.isProvided("geometry")
1710 && (use_geometry || nonstandard_papersize)) {
1711 odocstringstream ods;
1712 if (!getGraphicsDriver("geometry").empty())
1713 ods << getGraphicsDriver("geometry");
1714 if (orientation == ORIENTATION_LANDSCAPE)
1715 ods << ",landscape";
1716 switch (papersize) {
1718 if (!paperwidth.empty())
1719 ods << ",paperwidth="
1720 << from_ascii(paperwidth);
1721 if (!paperheight.empty())
1722 ods << ",paperheight="
1723 << from_ascii(paperheight);
1725 case PAPER_USLETTER:
1726 ods << ",letterpaper";
1729 ods << ",legalpaper";
1731 case PAPER_USEXECUTIVE:
1732 ods << ",executivepaper";
1821 docstring const g_options = trim(ods.str(), ",");
1822 os << "\\usepackage";
1823 if (!g_options.empty())
1824 os << '[' << g_options << ']';
1825 os << "{geometry}\n";
1826 // output this only if use_geometry is true
1828 os << "\\geometry{verbose";
1829 if (!topmargin.empty())
1830 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1831 if (!bottommargin.empty())
1832 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1833 if (!leftmargin.empty())
1834 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1835 if (!rightmargin.empty())
1836 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1837 if (!headheight.empty())
1838 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1839 if (!headsep.empty())
1840 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1841 if (!footskip.empty())
1842 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1843 if (!columnsep.empty())
1844 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1847 } else if (orientation == ORIENTATION_LANDSCAPE
1848 || papersize != PAPER_DEFAULT) {
1849 features.require("papersize");
1852 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1853 if (pagestyle == "fancy")
1854 os << "\\usepackage{fancyhdr}\n";
1855 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1858 // only output when the background color is not default
1859 if (isbackgroundcolor == true) {
1860 // only require color here, the background color will be defined
1861 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1863 features.require("color");
1864 features.require("pagecolor");
1867 // only output when the font color is not default
1868 if (isfontcolor == true) {
1869 // only require color here, the font color will be defined
1870 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1872 features.require("color");
1873 features.require("fontcolor");
1876 // Only if class has a ToC hierarchy
1877 if (tclass.hasTocLevels()) {
1878 if (secnumdepth != tclass.secnumdepth()) {
1879 os << "\\setcounter{secnumdepth}{"
1883 if (tocdepth != tclass.tocdepth()) {
1884 os << "\\setcounter{tocdepth}{"
1890 if (paragraph_separation) {
1891 // when skip separation
1892 switch (getDefSkip().kind()) {
1893 case VSpace::SMALLSKIP:
1894 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1896 case VSpace::MEDSKIP:
1897 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1899 case VSpace::BIGSKIP:
1900 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1902 case VSpace::LENGTH:
1903 os << "\\setlength{\\parskip}{"
1904 << from_utf8(getDefSkip().length().asLatexString())
1907 default: // should never happen // Then delete it.
1908 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1911 os << "\\setlength{\\parindent}{0pt}\n";
1913 // when separation by indentation
1914 // only output something when a width is given
1915 if (getIndentation().asLyXCommand() != "default") {
1916 os << "\\setlength{\\parindent}{"
1917 << from_utf8(getIndentation().asLatexCommand())
1922 // Now insert the LyX specific LaTeX commands...
1923 features.resolveAlternatives();
1924 features.expandMultiples();
1927 if (!output_sync_macro.empty())
1928 os << from_utf8(output_sync_macro) +"\n";
1929 else if (features.runparams().flavor == OutputParams::LATEX)
1930 os << "\\usepackage[active]{srcltx}\n";
1931 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1932 os << "\\synctex=-1\n";
1935 // The package options (via \PassOptionsToPackage)
1936 os << from_ascii(features.getPackageOptions());
1938 // due to interferences with babel and hyperref, the color package has to
1939 // be loaded (when it is not already loaded) before babel when hyperref
1940 // is used with the colorlinks option, see
1941 // http://www.lyx.org/trac/ticket/5291
1942 // we decided therefore to load color always before babel, see
1943 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1944 os << from_ascii(features.getColorOptions());
1946 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1947 // we have to call babel before
1949 && (features.isRequired("jurabib")
1950 || features.isRequired("hyperref")
1951 || features.isRequired("varioref")
1952 || features.isRequired("vietnamese")
1953 || features.isRequired("japanese"))) {
1954 os << features.getBabelPresettings();
1956 os << from_utf8(babelCall(language_options.str(),
1957 features.needBabelLangOptions())) + '\n';
1958 os << features.getBabelPostsettings();
1961 // The optional packages;
1962 os << from_ascii(features.getPackages());
1964 // Additional Indices
1965 if (features.isRequired("splitidx")) {
1966 IndicesList::const_iterator iit = indiceslist().begin();
1967 IndicesList::const_iterator iend = indiceslist().end();
1968 for (; iit != iend; ++iit) {
1969 os << "\\newindex{";
1970 os << escape(iit->shortcut());
1976 os << from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1979 // * Hyperref manual: "Make sure it comes last of your loaded
1980 // packages, to give it a fighting chance of not being over-written,
1981 // since its job is to redefine many LaTeX commands."
1982 // * Email from Heiko Oberdiek: "It is usually better to load babel
1983 // before hyperref. Then hyperref has a chance to detect babel.
1984 // * Has to be loaded before the "LyX specific LaTeX commands" to
1985 // avoid errors with algorithm floats.
1986 // use hyperref explicitly if it is required
1987 if (features.isRequired("hyperref")) {
1988 OutputParams tmp_params = features.runparams();
1989 pdfoptions().writeLaTeX(tmp_params, os,
1990 features.isProvided("hyperref"));
1991 // correctly break URLs with hyperref and dvi output
1992 if (features.runparams().flavor == OutputParams::LATEX
1993 && features.isAvailable("breakurl"))
1994 os << "\\usepackage{breakurl}\n";
1995 } else if (features.isRequired("nameref"))
1996 // hyperref loads this automatically
1997 os << "\\usepackage{nameref}\n";
1999 // bibtopic needs to be loaded after hyperref.
2000 // the dot provides the aux file naming which LyX can detect.
2001 if (features.mustProvide("bibtopic"))
2002 os << "\\usepackage[dot]{bibtopic}\n";
2004 // Will be surrounded by \makeatletter and \makeatother when not empty
2005 otexstringstream atlyxpreamble;
2007 // Some macros LyX will need
2009 TexString tmppreamble = features.getMacros();
2010 if (!tmppreamble.str.empty())
2011 atlyxpreamble << "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2012 "LyX specific LaTeX commands.\n"
2013 << move(tmppreamble)
2016 // the text class specific preamble
2018 docstring tmppreamble = features.getTClassPreamble();
2019 if (!tmppreamble.empty())
2020 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2021 "Textclass specific LaTeX commands.\n"
2025 // suppress date if selected
2026 // use \@ifundefined because we cannot be sure that every document class
2027 // has a \date command
2029 atlyxpreamble << "\\@ifundefined{date}{}{\\date{}}\n";
2031 /* the user-defined preamble */
2032 if (!containsOnly(preamble, " \n\t")) {
2034 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2035 "User specified LaTeX commands.\n";
2037 // Check if the user preamble contains uncodable glyphs
2038 odocstringstream user_preamble;
2039 docstring uncodable_glyphs;
2040 Encoding const * const enc = features.runparams().encoding;
2042 for (size_t n = 0; n < preamble.size(); ++n) {
2043 char_type c = preamble[n];
2044 if (!enc->encodable(c)) {
2045 docstring const glyph(1, c);
2046 LYXERR0("Uncodable character '"
2048 << "' in user preamble!");
2049 uncodable_glyphs += glyph;
2050 if (features.runparams().dryrun) {
2051 user_preamble << "<" << _("LyX Warning: ")
2052 << _("uncodable character") << " '";
2053 user_preamble.put(c);
2054 user_preamble << "'>";
2057 user_preamble.put(c);
2060 user_preamble << preamble;
2062 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2063 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2064 frontend::Alert::warning(
2065 _("Uncodable character in user preamble"),
2067 _("The user preamble of your document contains glyphs "
2068 "that are unknown in the current document encoding "
2069 "(namely %1$s).\nThese glyphs are omitted "
2070 " from the output, which may result in "
2071 "incomplete output."
2072 "\n\nPlease select an appropriate "
2073 "document encoding\n"
2074 "(such as utf8) or change the "
2075 "preamble code accordingly."),
2078 atlyxpreamble << user_preamble.str() << '\n';
2081 // footmisc must be loaded after setspace
2082 // Load it here to avoid clashes with footmisc loaded in the user
2083 // preamble. For that reason we also pass the options via
2084 // \PassOptionsToPackage in getPreamble() and not here.
2085 if (features.mustProvide("footmisc"))
2086 atlyxpreamble << "\\usepackage{footmisc}\n";
2088 // subfig loads internally the LaTeX package "caption". As
2089 // caption is a very popular package, users will load it in
2090 // the preamble. Therefore we must load subfig behind the
2091 // user-defined preamble and check if the caption package was
2092 // loaded or not. For the case that caption is loaded before
2093 // subfig, there is the subfig option "caption=false". This
2094 // option also works when a koma-script class is used and
2095 // koma's own caption commands are used instead of caption. We
2096 // use \PassOptionsToPackage here because the user could have
2097 // already loaded subfig in the preamble.
2098 if (features.mustProvide("subfig"))
2099 atlyxpreamble << "\\@ifundefined{showcaptionsetup}{}{%\n"
2100 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2101 "\\usepackage{subfig}\n";
2103 // Itemize bullet settings need to be last in case the user
2104 // defines their own bullets that use a package included
2105 // in the user-defined preamble -- ARRae
2106 // Actually it has to be done much later than that
2107 // since some packages like frenchb make modifications
2108 // at \begin{document} time -- JMarc
2109 docstring bullets_def;
2110 for (int i = 0; i < 4; ++i) {
2111 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2112 if (bullets_def.empty())
2113 bullets_def += "\\AtBeginDocument{\n";
2114 bullets_def += " \\def\\labelitemi";
2116 // `i' is one less than the item to modify
2123 bullets_def += "ii";
2129 bullets_def += '{' +
2130 user_defined_bullet(i).getText()
2135 if (!bullets_def.empty())
2136 atlyxpreamble << bullets_def << "}\n\n";
2138 if (!atlyxpreamble.empty())
2139 os << "\n\\makeatletter\n"
2140 << atlyxpreamble.release()
2141 << "\\makeatother\n\n";
2143 // We try to load babel late, in case it interferes with other packages.
2144 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2145 // called after babel, though.
2146 if (use_babel && !features.isRequired("jurabib")
2147 && !features.isRequired("hyperref")
2148 && !features.isRequired("varioref")
2149 && !features.isRequired("vietnamese")
2150 && !features.isRequired("japanese")) {
2151 os << features.getBabelPresettings();
2153 os << from_utf8(babelCall(language_options.str(),
2154 features.needBabelLangOptions())) + '\n';
2155 os << features.getBabelPostsettings();
2157 if (features.isRequired("bicaption"))
2158 os << "\\usepackage{bicaption}\n";
2159 if (!listings_params.empty() || features.mustProvide("listings"))
2160 os << "\\usepackage{listings}\n";
2161 if (!listings_params.empty()) {
2163 // do not test validity because listings_params is
2164 // supposed to be valid
2166 InsetListingsParams(listings_params).separatedParams(true);
2167 os << from_utf8(par);
2171 // xunicode needs to be loaded at least after amsmath, amssymb,
2172 // esint and the other packages that provide special glyphs
2173 // The package only supports XeTeX currently.
2174 if (features.runparams().flavor == OutputParams::XETEX
2176 os << "\\usepackage{xunicode}\n";
2178 // Polyglossia must be loaded last ...
2179 if (use_polyglossia) {
2181 os << "\\usepackage{polyglossia}\n";
2182 // set the main language
2183 os << "\\setdefaultlanguage";
2184 if (!language->polyglossiaOpts().empty())
2185 os << "[" << from_ascii(language->polyglossiaOpts()) << "]";
2186 os << "{" << from_ascii(language->polyglossia()) << "}\n";
2187 // now setup the other languages
2188 set<string> const polylangs =
2189 features.getPolyglossiaLanguages();
2190 for (set<string>::const_iterator mit = polylangs.begin();
2191 mit != polylangs.end() ; ++mit) {
2192 // We do not output the options here; they are output in
2193 // the language switch commands. This is safer if multiple
2194 // varieties are used.
2195 if (*mit == language->polyglossia())
2197 os << "\\setotherlanguage";
2198 os << "{" << from_ascii(*mit) << "}\n";
2202 // ... but before biblatex (see #7065)
2203 if (features.mustProvide("biblatex")) {
2206 os << "\\usepackage";
2207 if (!biblatex_bibstyle.empty()
2208 && (biblatex_bibstyle == biblatex_citestyle)) {
2209 opts = "style=" + biblatex_bibstyle;
2212 if (!biblatex_bibstyle.empty()) {
2213 opts = "bibstyle=" + biblatex_bibstyle;
2216 if (!biblatex_citestyle.empty()) {
2217 opts += delim + "citestyle=" + biblatex_citestyle;
2221 if (!multibib.empty()) {
2222 opts += delim + "refsection=" + multibib;
2225 if (bibtexCommand() == "bibtex8"
2226 || prefixIs(bibtexCommand(), "bibtex8 ")) {
2227 opts += delim + "backend=bibtex8";
2229 } else if (bibtexCommand() == "bibtex"
2230 || prefixIs(bibtexCommand(), "bibtex ")) {
2231 opts += delim + "backend=bibtex";
2234 if (!biblio_opts.empty())
2235 opts += delim + biblio_opts;
2237 os << "[" << opts << "]";
2238 os << "{biblatex}\n";
2242 // Load custom language package here
2243 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2244 if (lang_package == "default")
2245 os << from_utf8(lyxrc.language_custom_package);
2247 os << from_utf8(lang_package);
2251 docstring const i18npreamble =
2252 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2253 if (!i18npreamble.empty())
2254 os << i18npreamble + '\n';
2260 void BufferParams::useClassDefaults()
2262 DocumentClass const & tclass = documentClass();
2264 sides = tclass.sides();
2265 columns = tclass.columns();
2266 pagestyle = tclass.pagestyle();
2267 use_default_options = true;
2268 // Only if class has a ToC hierarchy
2269 if (tclass.hasTocLevels()) {
2270 secnumdepth = tclass.secnumdepth();
2271 tocdepth = tclass.tocdepth();
2276 bool BufferParams::hasClassDefaults() const
2278 DocumentClass const & tclass = documentClass();
2280 return sides == tclass.sides()
2281 && columns == tclass.columns()
2282 && pagestyle == tclass.pagestyle()
2283 && use_default_options
2284 && secnumdepth == tclass.secnumdepth()
2285 && tocdepth == tclass.tocdepth();
2289 DocumentClass const & BufferParams::documentClass() const
2295 DocumentClassConstPtr BufferParams::documentClassPtr() const
2301 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2303 // evil, but this function is evil
2304 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2305 invalidateConverterCache();
2309 bool BufferParams::setBaseClass(string const & classname)
2311 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2312 LayoutFileList & bcl = LayoutFileList::get();
2313 if (!bcl.haveClass(classname)) {
2315 bformat(_("The layout file:\n"
2317 "could not be found. A default textclass with default\n"
2318 "layouts will be used. LyX will not be able to produce\n"
2320 from_utf8(classname));
2321 frontend::Alert::error(_("Document class not found"), s);
2322 bcl.addEmptyClass(classname);
2325 bool const success = bcl[classname].load();
2328 bformat(_("Due to some error in it, the layout file:\n"
2330 "could not be loaded. A default textclass with default\n"
2331 "layouts will be used. LyX will not be able to produce\n"
2333 from_utf8(classname));
2334 frontend::Alert::error(_("Could not load class"), s);
2335 bcl.addEmptyClass(classname);
2338 pimpl_->baseClass_ = classname;
2339 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2344 LayoutFile const * BufferParams::baseClass() const
2346 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2347 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2353 LayoutFileIndex const & BufferParams::baseClassID() const
2355 return pimpl_->baseClass_;
2359 void BufferParams::makeDocumentClass(bool const clone)
2364 invalidateConverterCache();
2365 LayoutModuleList mods;
2366 LayoutModuleList ces;
2367 LayoutModuleList::iterator it = layout_modules_.begin();
2368 LayoutModuleList::iterator en = layout_modules_.end();
2369 for (; it != en; ++it)
2370 mods.push_back(*it);
2372 it = cite_engine_.begin();
2373 en = cite_engine_.end();
2374 for (; it != en; ++it)
2377 doc_class_ = getDocumentClass(*baseClass(), mods, ces, clone);
2379 TextClass::ReturnValues success = TextClass::OK;
2380 if (!forced_local_layout_.empty())
2381 success = doc_class_->read(to_utf8(forced_local_layout_),
2383 if (!local_layout_.empty() &&
2384 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2385 success = doc_class_->read(to_utf8(local_layout_), TextClass::MODULE);
2386 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2387 docstring const msg = _("Error reading internal layout information");
2388 frontend::Alert::warning(_("Read Error"), msg);
2393 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2395 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2399 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2401 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2405 docstring BufferParams::getLocalLayout(bool forced) const
2408 return from_utf8(doc_class_->forcedLayouts());
2410 return local_layout_;
2414 void BufferParams::setLocalLayout(docstring const & layout, bool forced)
2417 forced_local_layout_ = layout;
2419 local_layout_ = layout;
2423 bool BufferParams::addLayoutModule(string const & modName)
2425 LayoutModuleList::const_iterator it = layout_modules_.begin();
2426 LayoutModuleList::const_iterator end = layout_modules_.end();
2427 for (; it != end; ++it)
2430 layout_modules_.push_back(modName);
2435 string BufferParams::bufferFormat() const
2437 return documentClass().outputFormat();
2441 bool BufferParams::isExportable(string const & format, bool need_viewable) const
2443 FormatList const & formats = exportableFormats(need_viewable);
2444 FormatList::const_iterator fit = formats.begin();
2445 FormatList::const_iterator end = formats.end();
2446 for (; fit != end ; ++fit) {
2447 if ((*fit)->name() == format)
2454 FormatList const & BufferParams::exportableFormats(bool only_viewable) const
2456 FormatList & cached = only_viewable ?
2457 pimpl_->viewableFormatList : pimpl_->exportableFormatList;
2458 bool & valid = only_viewable ?
2459 pimpl_->isViewCacheValid : pimpl_->isExportCacheValid;
2463 vector<string> const backs = backends();
2464 set<string> excludes;
2465 if (useNonTeXFonts) {
2466 excludes.insert("latex");
2467 excludes.insert("pdflatex");
2470 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2471 for (vector<string>::const_iterator it = backs.begin() + 1;
2472 it != backs.end(); ++it) {
2473 FormatList r = theConverters().getReachable(*it, only_viewable,
2475 result.insert(result.end(), r.begin(), r.end());
2477 sort(result.begin(), result.end(), Format::formatSorter);
2484 vector<string> BufferParams::backends() const
2487 string const buffmt = bufferFormat();
2489 // FIXME: Don't hardcode format names here, but use a flag
2490 if (buffmt == "latex") {
2491 if (encoding().package() == Encoding::japanese)
2492 v.push_back("platex");
2494 if (!useNonTeXFonts) {
2495 v.push_back("pdflatex");
2496 v.push_back("latex");
2498 v.push_back("xetex");
2499 v.push_back("luatex");
2500 v.push_back("dviluatex");
2503 v.push_back(buffmt);
2505 v.push_back("xhtml");
2506 v.push_back("text");
2512 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2514 string const dformat = (format.empty() || format == "default") ?
2515 getDefaultOutputFormat() : format;
2516 DefaultFlavorCache::const_iterator it =
2517 default_flavors_.find(dformat);
2519 if (it != default_flavors_.end())
2522 OutputParams::FLAVOR result = OutputParams::LATEX;
2524 // FIXME It'd be better not to hardcode this, but to do
2525 // something with formats.
2526 if (dformat == "xhtml")
2527 result = OutputParams::HTML;
2528 else if (dformat == "text")
2529 result = OutputParams::TEXT;
2530 else if (dformat == "lyx")
2531 result = OutputParams::LYX;
2532 else if (dformat == "pdflatex")
2533 result = OutputParams::PDFLATEX;
2534 else if (dformat == "xetex")
2535 result = OutputParams::XETEX;
2536 else if (dformat == "luatex")
2537 result = OutputParams::LUATEX;
2538 else if (dformat == "dviluatex")
2539 result = OutputParams::DVILUATEX;
2541 // Try to determine flavor of default output format
2542 vector<string> backs = backends();
2543 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2544 // Get shortest path to format
2545 Graph::EdgePath path;
2546 for (vector<string>::const_iterator it = backs.begin();
2547 it != backs.end(); ++it) {
2548 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2549 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2554 result = theConverters().getFlavor(path);
2557 // cache this flavor
2558 default_flavors_[dformat] = result;
2563 string BufferParams::getDefaultOutputFormat() const
2565 if (!default_output_format.empty()
2566 && default_output_format != "default")
2567 return default_output_format;
2569 || encoding().package() == Encoding::japanese) {
2570 FormatList const & formats = exportableFormats(true);
2571 if (formats.empty())
2573 // return the first we find
2574 return formats.front()->name();
2577 return lyxrc.default_otf_view_format;
2578 return lyxrc.default_view_format;
2581 Font const BufferParams::getFont() const
2583 FontInfo f = documentClass().defaultfont();
2584 if (fonts_default_family == "rmdefault")
2585 f.setFamily(ROMAN_FAMILY);
2586 else if (fonts_default_family == "sfdefault")
2587 f.setFamily(SANS_FAMILY);
2588 else if (fonts_default_family == "ttdefault")
2589 f.setFamily(TYPEWRITER_FAMILY);
2590 return Font(f, language);
2594 InsetQuotesParams::QuoteStyle BufferParams::getQuoteStyle(string const & qs) const
2596 return quotesstyletranslator().find(qs);
2600 bool BufferParams::isLatex() const
2602 return documentClass().outputType() == LATEX;
2606 bool BufferParams::isLiterate() const
2608 return documentClass().outputType() == LITERATE;
2612 bool BufferParams::isDocBook() const
2614 return documentClass().outputType() == DOCBOOK;
2618 void BufferParams::readPreamble(Lexer & lex)
2620 if (lex.getString() != "\\begin_preamble")
2621 lyxerr << "Error (BufferParams::readPreamble):"
2622 "consistency check failed." << endl;
2624 preamble = lex.getLongString(from_ascii("\\end_preamble"));
2628 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2630 string const expected = forced ? "\\begin_forced_local_layout" :
2631 "\\begin_local_layout";
2632 if (lex.getString() != expected)
2633 lyxerr << "Error (BufferParams::readLocalLayout):"
2634 "consistency check failed." << endl;
2637 forced_local_layout_ =
2638 lex.getLongString(from_ascii("\\end_forced_local_layout"));
2640 local_layout_ = lex.getLongString(from_ascii("\\end_local_layout"));
2644 bool BufferParams::setLanguage(string const & lang)
2646 Language const *new_language = languages.getLanguage(lang);
2647 if (!new_language) {
2648 // Language lang was not found
2651 language = new_language;
2656 void BufferParams::readLanguage(Lexer & lex)
2658 if (!lex.next()) return;
2660 string const tmptok = lex.getString();
2662 // check if tmptok is part of tex_babel in tex-defs.h
2663 if (!setLanguage(tmptok)) {
2664 // Language tmptok was not found
2665 language = default_language;
2666 lyxerr << "Warning: Setting language `"
2667 << tmptok << "' to `" << language->lang()
2673 void BufferParams::readGraphicsDriver(Lexer & lex)
2678 string const tmptok = lex.getString();
2679 // check if tmptok is part of tex_graphics in tex_defs.h
2682 string const test = tex_graphics[n++];
2684 if (test == tmptok) {
2685 graphics_driver = tmptok;
2690 "Warning: graphics driver `$$Token' not recognized!\n"
2691 " Setting graphics driver to `default'.\n");
2692 graphics_driver = "default";
2699 void BufferParams::readBullets(Lexer & lex)
2704 int const index = lex.getInteger();
2706 int temp_int = lex.getInteger();
2707 user_defined_bullet(index).setFont(temp_int);
2708 temp_bullet(index).setFont(temp_int);
2710 user_defined_bullet(index).setCharacter(temp_int);
2711 temp_bullet(index).setCharacter(temp_int);
2713 user_defined_bullet(index).setSize(temp_int);
2714 temp_bullet(index).setSize(temp_int);
2718 void BufferParams::readBulletsLaTeX(Lexer & lex)
2720 // The bullet class should be able to read this.
2723 int const index = lex.getInteger();
2725 docstring const temp_str = lex.getDocString();
2727 user_defined_bullet(index).setText(temp_str);
2728 temp_bullet(index).setText(temp_str);
2732 void BufferParams::readModules(Lexer & lex)
2734 if (!lex.eatLine()) {
2735 lyxerr << "Error (BufferParams::readModules):"
2736 "Unexpected end of input." << endl;
2740 string mod = lex.getString();
2741 if (mod == "\\end_modules")
2743 addLayoutModule(mod);
2749 void BufferParams::readRemovedModules(Lexer & lex)
2751 if (!lex.eatLine()) {
2752 lyxerr << "Error (BufferParams::readRemovedModules):"
2753 "Unexpected end of input." << endl;
2757 string mod = lex.getString();
2758 if (mod == "\\end_removed_modules")
2760 removed_modules_.push_back(mod);
2763 // now we want to remove any removed modules that were previously
2764 // added. normally, that will be because default modules were added in
2765 // setBaseClass(), which gets called when \textclass is read at the
2766 // start of the read.
2767 list<string>::const_iterator rit = removed_modules_.begin();
2768 list<string>::const_iterator const ren = removed_modules_.end();
2769 for (; rit != ren; ++rit) {
2770 LayoutModuleList::iterator const mit = layout_modules_.begin();
2771 LayoutModuleList::iterator const men = layout_modules_.end();
2772 LayoutModuleList::iterator found = find(mit, men, *rit);
2775 layout_modules_.erase(found);
2780 void BufferParams::readIncludeonly(Lexer & lex)
2782 if (!lex.eatLine()) {
2783 lyxerr << "Error (BufferParams::readIncludeonly):"
2784 "Unexpected end of input." << endl;
2788 string child = lex.getString();
2789 if (child == "\\end_includeonly")
2791 included_children_.push_back(child);
2797 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2799 switch (papersize) {
2801 // could be anything, so don't guess
2803 case PAPER_CUSTOM: {
2804 if (purpose == XDVI && !paperwidth.empty() &&
2805 !paperheight.empty()) {
2806 // heightxwidth<unit>
2807 string first = paperwidth;
2808 string second = paperheight;
2809 if (orientation == ORIENTATION_LANDSCAPE)
2812 return first.erase(first.length() - 2)
2818 // dvips and dvipdfm do not know this
2819 if (purpose == DVIPS || purpose == DVIPDFM)
2823 if (purpose == DVIPS || purpose == DVIPDFM)
2827 if (purpose == DVIPS || purpose == DVIPDFM)
2837 if (purpose == DVIPS || purpose == DVIPDFM)
2841 if (purpose == DVIPS || purpose == DVIPDFM)
2845 if (purpose == DVIPS || purpose == DVIPDFM)
2849 if (purpose == DVIPS || purpose == DVIPDFM)
2853 if (purpose == DVIPS || purpose == DVIPDFM)
2857 // dvipdfm does not know this
2858 if (purpose == DVIPDFM)
2862 if (purpose == DVIPDFM)
2866 if (purpose == DVIPS || purpose == DVIPDFM)
2870 if (purpose == DVIPS || 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)
2925 case PAPER_USEXECUTIVE:
2926 // dvipdfm does not know this
2927 if (purpose == DVIPDFM)
2932 case PAPER_USLETTER:
2934 if (purpose == XDVI)
2941 string const BufferParams::dvips_options() const
2945 // If the class loads the geometry package, we do not know which
2946 // paper size is used, since we do not set it (bug 7013).
2947 // Therefore we must not specify any argument here.
2948 // dvips gets the correct paper size via DVI specials in this case
2949 // (if the class uses the geometry package correctly).
2950 if (documentClass().provides("geometry"))
2954 && papersize == PAPER_CUSTOM
2955 && !lyxrc.print_paper_dimension_flag.empty()
2956 && !paperwidth.empty()
2957 && !paperheight.empty()) {
2958 // using a custom papersize
2959 result = lyxrc.print_paper_dimension_flag;
2960 result += ' ' + paperwidth;
2961 result += ',' + paperheight;
2963 string const paper_option = paperSizeName(DVIPS);
2964 if (!paper_option.empty() && (paper_option != "letter" ||
2965 orientation != ORIENTATION_LANDSCAPE)) {
2966 // dvips won't accept -t letter -t landscape.
2967 // In all other cases, include the paper size
2969 result = lyxrc.print_paper_flag;
2970 result += ' ' + paper_option;
2973 if (orientation == ORIENTATION_LANDSCAPE &&
2974 papersize != PAPER_CUSTOM)
2975 result += ' ' + lyxrc.print_landscape_flag;
2980 string const BufferParams::font_encoding() const
2982 return font_encodings().empty() ? "default" : font_encodings().back();
2986 vector<string> const BufferParams::font_encodings() const
2988 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2990 vector<string> fontencs;
2992 // "default" means "no explicit font encoding"
2993 if (doc_fontenc != "default") {
2994 fontencs = getVectorFromString(doc_fontenc);
2995 if (!language->fontenc().empty()
2996 && ascii_lowercase(language->fontenc()) != "none") {
2997 vector<string> fencs = getVectorFromString(language->fontenc());
2998 vector<string>::const_iterator fit = fencs.begin();
2999 for (; fit != fencs.end(); ++fit) {
3000 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
3001 fontencs.push_back(*fit);
3010 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
3012 // suppress the babel call if there is no BabelName defined
3013 // for the document language in the lib/languages file and if no
3014 // other languages are used (lang_opts is then empty)
3015 if (lang_opts.empty())
3017 // either a specific language (AsBabelOptions setting in
3018 // lib/languages) or the prefs require the languages to
3019 // be submitted to babel itself (not the class).
3021 return "\\usepackage[" + lang_opts + "]{babel}";
3022 return "\\usepackage{babel}";
3026 docstring BufferParams::getGraphicsDriver(string const & package) const
3030 if (package == "geometry") {
3031 if (graphics_driver == "dvips"
3032 || graphics_driver == "dvipdfm"
3033 || graphics_driver == "pdftex"
3034 || graphics_driver == "vtex")
3035 result = from_ascii(graphics_driver);
3036 else if (graphics_driver == "dvipdfmx")
3037 result = from_ascii("dvipdfm");
3044 void BufferParams::writeEncodingPreamble(otexstream & os,
3045 LaTeXFeatures & features) const
3047 // XeTeX/LuaTeX: (see also #9740)
3048 // With Unicode fonts we use utf8-plain without encoding package.
3049 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
3050 // XeTeX must use ASCII encoding (see Buffer.cpp),
3051 // for LuaTeX, we load "luainputenc" (see below).
3052 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
3055 if (inputenc == "auto") {
3056 string const doc_encoding =
3057 language->encoding()->latexName();
3058 Encoding::Package const package =
3059 language->encoding()->package();
3061 // Create list of inputenc options:
3062 set<string> encodings;
3063 // luainputenc fails with more than one encoding
3064 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
3065 // list all input encodings used in the document
3066 encodings = features.getEncodingSet(doc_encoding);
3068 // If the "japanese" package (i.e. pLaTeX) is used,
3069 // inputenc must be omitted.
3070 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
3071 if ((!encodings.empty() || package == Encoding::inputenc)
3072 && !features.isRequired("japanese")
3073 && !features.isProvided("inputenc")) {
3074 os << "\\usepackage[";
3075 set<string>::const_iterator it = encodings.begin();
3076 set<string>::const_iterator const end = encodings.end();
3078 os << from_ascii(*it);
3081 for (; it != end; ++it)
3082 os << ',' << from_ascii(*it);
3083 if (package == Encoding::inputenc) {
3084 if (!encodings.empty())
3086 os << from_ascii(doc_encoding);
3088 if (features.runparams().flavor == OutputParams::LUATEX
3089 || features.runparams().flavor == OutputParams::DVILUATEX)
3090 os << "]{luainputenc}\n";
3092 os << "]{inputenc}\n";
3094 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3095 if (language->encoding()->name() == "utf8-cjk"
3096 && LaTeXFeatures::isAvailable("CJKutf8"))
3097 os << "\\usepackage{CJKutf8}\n";
3099 os << "\\usepackage{CJK}\n";
3101 } else if (inputenc != "default") {
3102 switch (encoding().package()) {
3103 case Encoding::none:
3104 case Encoding::japanese:
3106 case Encoding::inputenc:
3107 // do not load inputenc if japanese is used
3108 // or if the class provides inputenc
3109 if (features.isRequired("japanese")
3110 || features.isProvided("inputenc"))
3112 os << "\\usepackage[" << from_ascii(encoding().latexName());
3113 if (features.runparams().flavor == OutputParams::LUATEX
3114 || features.runparams().flavor == OutputParams::DVILUATEX)
3115 os << "]{luainputenc}\n";
3117 os << "]{inputenc}\n";
3120 if (encoding().name() == "utf8-cjk"
3121 && LaTeXFeatures::isAvailable("CJKutf8"))
3122 os << "\\usepackage{CJKutf8}\n";
3124 os << "\\usepackage{CJK}\n";
3127 // Load the CJK package if needed by a secondary language.
3128 // If the main encoding is some variant of UTF8, use CJKutf8.
3129 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3130 if (encoding().iconvName() == "UTF-8"
3131 && LaTeXFeatures::isAvailable("CJKutf8"))
3132 os << "\\usepackage{CJKutf8}\n";
3134 os << "\\usepackage{CJK}\n";
3140 string const BufferParams::parseFontName(string const & name) const
3142 string mangled = name;
3143 size_t const idx = mangled.find('[');
3144 if (idx == string::npos || idx == 0)
3147 return mangled.substr(0, idx - 1);
3151 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3153 if (fontsRoman() == "default" && fontsSans() == "default"
3154 && fontsTypewriter() == "default"
3155 && (fontsMath() == "default" || fontsMath() == "auto"))
3161 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3162 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3163 * Mapping=tex-text option assures TeX ligatures (such as "--")
3164 * are resolved. Note that tt does not use these ligatures.
3166 * -- add more GUI options?
3167 * -- add more fonts (fonts for other scripts)
3168 * -- if there's a way to find out if a font really supports
3169 * OldStyle, enable/disable the widget accordingly.
3171 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3172 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3173 // However, until v.2 (2010/07/11) fontspec only knew
3174 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3175 // was introduced for both XeTeX and LuaTeX (LuaTeX
3176 // didn't understand "Mapping=tex-text", while XeTeX
3177 // understood both. With most recent versions, both
3178 // variants are understood by both engines. However,
3179 // we want to provide support for at least TeXLive 2009
3180 // (for XeTeX; LuaTeX is only supported as of v.2)
3181 string const texmapping =
3182 (features.runparams().flavor == OutputParams::XETEX) ?
3183 "Mapping=tex-text" : "Ligatures=TeX";
3184 if (fontsRoman() != "default") {
3185 os << "\\setmainfont[" << texmapping;
3186 if (fonts_old_figures)
3187 os << ",Numbers=OldStyle";
3188 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3190 if (fontsSans() != "default") {
3191 string const sans = parseFontName(fontsSans());
3192 if (fontsSansScale() != 100)
3193 os << "\\setsansfont[Scale="
3194 << float(fontsSansScale()) / 100
3195 << "," << texmapping << "]{"
3198 os << "\\setsansfont[" << texmapping << "]{"
3201 if (fontsTypewriter() != "default") {
3202 string const mono = parseFontName(fontsTypewriter());
3203 if (fontsTypewriterScale() != 100)
3204 os << "\\setmonofont[Scale="
3205 << float(fontsTypewriterScale()) / 100
3209 os << "\\setmonofont{"
3216 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3217 bool const dryrun = features.runparams().dryrun;
3218 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3219 bool const nomath = (fontsMath() == "default");
3222 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3223 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3227 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3228 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3229 nomath, fontsSansScale());
3231 // MONOSPACED/TYPEWRITER
3232 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3233 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3234 nomath, fontsTypewriterScale());
3237 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3238 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3245 Encoding const & BufferParams::encoding() const
3247 // Main encoding for LaTeX output.
3249 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3250 // As the "flavor" is only known once export started, this
3251 // cannot be handled here. Instead, runparams.encoding is set
3252 // to ASCII in Buffer::makeLaTeXFile (for export)
3253 // and Buffer::writeLaTeXSource (for preview).
3255 return *(encodings.fromLyXName("utf8-plain"));
3256 if (inputenc == "auto" || inputenc == "default")
3257 return *language->encoding();
3258 Encoding const * const enc = encodings.fromLyXName(inputenc);
3261 LYXERR0("Unknown inputenc value `" << inputenc
3262 << "'. Using `auto' instead.");
3263 return *language->encoding();
3267 bool BufferParams::addCiteEngine(string const & engine)
3269 LayoutModuleList::const_iterator it = cite_engine_.begin();
3270 LayoutModuleList::const_iterator en = cite_engine_.end();
3271 for (; it != en; ++it)
3274 cite_engine_.push_back(engine);
3279 bool BufferParams::addCiteEngine(vector<string> const & engine)
3281 vector<string>::const_iterator it = engine.begin();
3282 vector<string>::const_iterator en = engine.end();
3284 for (; it != en; ++it)
3285 if (!addCiteEngine(*it))
3291 string const & BufferParams::defaultBiblioStyle() const
3293 map<string, string> bs = documentClass().defaultBiblioStyle();
3294 return bs[theCiteEnginesList.getTypeAsString(citeEngineType())];
3298 bool const & BufferParams::fullAuthorList() const
3300 return documentClass().fullAuthorList();
3304 string BufferParams::getCiteAlias(string const & s) const
3306 vector<string> commands =
3307 documentClass().citeCommands(citeEngineType());
3308 // If it is a real command, don't treat it as an alias
3309 if (find(commands.begin(), commands.end(), s) != commands.end())
3311 map<string,string> aliases = documentClass().citeCommandAliases();
3312 if (aliases.find(s) != aliases.end())
3318 void BufferParams::setCiteEngine(string const & engine)
3321 addCiteEngine(engine);
3325 void BufferParams::setCiteEngine(vector<string> const & engine)
3328 addCiteEngine(engine);
3332 vector<string> BufferParams::citeCommands() const
3334 static CitationStyle const default_style;
3335 vector<string> commands =
3336 documentClass().citeCommands(citeEngineType());
3337 if (commands.empty())
3338 commands.push_back(default_style.name);
3343 vector<CitationStyle> BufferParams::citeStyles() const
3345 static CitationStyle const default_style;
3346 vector<CitationStyle> styles =
3347 documentClass().citeStyles(citeEngineType());
3349 styles.push_back(default_style);
3354 string const BufferParams::bibtexCommand() const
3356 // Return document-specific setting if available
3357 if (bibtex_command != "default")
3358 return bibtex_command;
3360 // If we have "default" in document settings, consult the prefs
3361 // 1. Japanese (uses a specific processor)
3362 if (encoding().package() == Encoding::japanese) {
3363 if (lyxrc.jbibtex_command != "automatic")
3364 // Return the specified program, if "automatic" is not set
3365 return lyxrc.jbibtex_command;
3366 else if (!useBiblatex()) {
3367 // With classic BibTeX, return pbibtex, jbibtex, bibtex
3368 if (lyxrc.jbibtex_alternatives.find("pbibtex") != lyxrc.jbibtex_alternatives.end())
3370 if (lyxrc.jbibtex_alternatives.find("jbibtex") != lyxrc.jbibtex_alternatives.end())
3375 // 2. All other languages
3376 else if (lyxrc.bibtex_command != "automatic")
3377 // Return the specified program, if "automatic" is not set
3378 return lyxrc.bibtex_command;
3380 // 3. Automatic: find the most suitable for the current cite framework
3381 if (useBiblatex()) {
3382 // For Biblatex, we prefer biber (also for Japanese)
3383 // and fall back to bibtex8 and, as last resort, bibtex
3384 if (lyxrc.bibtex_alternatives.find("biber") != lyxrc.bibtex_alternatives.end())
3386 else if (lyxrc.bibtex_alternatives.find("bibtex8") != lyxrc.bibtex_alternatives.end())
3393 bool BufferParams::useBiblatex() const
3395 return theCiteEnginesList[citeEngine().list().front()]
3396 ->getCiteFramework() == "biblatex";
3400 void BufferParams::invalidateConverterCache() const
3402 pimpl_->isExportCacheValid = false;
3403 pimpl_->isViewCacheValid = false;