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 = (main_font_encoding() == "default" || main_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 && main_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 only needs to be loaded if tipa is used
2180 // (the rest is obsoleted by the new TU encoding).
2181 // It needs to be loaded at least after amsmath, amssymb,
2182 // esint and the other packages that provide special glyphs
2183 if (features.mustProvide("tipa") && useNonTeXFonts) {
2184 // The package officially only supports XeTeX, but also works
2185 // with LuaTeX. Thus we work around its XeTeX test.
2186 if (features.runparams().flavor != OutputParams::XETEX) {
2187 os << "% Pretend to xunicode that we are XeTeX\n"
2188 << "\\def\\XeTeXpicfile{}\n";
2190 os << "\\usepackage{xunicode}\n";
2193 // Polyglossia must be loaded last ...
2194 if (use_polyglossia) {
2196 os << "\\usepackage{polyglossia}\n";
2197 // set the main language
2198 os << "\\setdefaultlanguage";
2199 if (!language->polyglossiaOpts().empty())
2200 os << "[" << from_ascii(language->polyglossiaOpts()) << "]";
2201 os << "{" << from_ascii(language->polyglossia()) << "}\n";
2202 // now setup the other languages
2203 set<string> const polylangs =
2204 features.getPolyglossiaLanguages();
2205 for (set<string>::const_iterator mit = polylangs.begin();
2206 mit != polylangs.end() ; ++mit) {
2207 // We do not output the options here; they are output in
2208 // the language switch commands. This is safer if multiple
2209 // varieties are used.
2210 if (*mit == language->polyglossia())
2212 os << "\\setotherlanguage";
2213 os << "{" << from_ascii(*mit) << "}\n";
2217 // ... but before biblatex (see #7065)
2218 if (features.mustProvide("biblatex")) {
2221 os << "\\usepackage";
2222 if (!biblatex_bibstyle.empty()
2223 && (biblatex_bibstyle == biblatex_citestyle)) {
2224 opts = "style=" + biblatex_bibstyle;
2227 if (!biblatex_bibstyle.empty()) {
2228 opts = "bibstyle=" + biblatex_bibstyle;
2231 if (!biblatex_citestyle.empty()) {
2232 opts += delim + "citestyle=" + biblatex_citestyle;
2236 if (!multibib.empty() && multibib != "child") {
2237 opts += delim + "refsection=" + multibib;
2240 if (bibtexCommand() == "bibtex8"
2241 || prefixIs(bibtexCommand(), "bibtex8 ")) {
2242 opts += delim + "backend=bibtex8";
2244 } else if (bibtexCommand() == "bibtex"
2245 || prefixIs(bibtexCommand(), "bibtex ")) {
2246 opts += delim + "backend=bibtex";
2249 if (!biblio_opts.empty())
2250 opts += delim + biblio_opts;
2252 os << "[" << opts << "]";
2253 os << "{biblatex}\n";
2257 // Load custom language package here
2258 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2259 if (lang_package == "default")
2260 os << from_utf8(lyxrc.language_custom_package);
2262 os << from_utf8(lang_package);
2266 docstring const i18npreamble =
2267 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2268 if (!i18npreamble.empty())
2269 os << i18npreamble + '\n';
2275 void BufferParams::useClassDefaults()
2277 DocumentClass const & tclass = documentClass();
2279 sides = tclass.sides();
2280 columns = tclass.columns();
2281 pagestyle = tclass.pagestyle();
2282 use_default_options = true;
2283 // Only if class has a ToC hierarchy
2284 if (tclass.hasTocLevels()) {
2285 secnumdepth = tclass.secnumdepth();
2286 tocdepth = tclass.tocdepth();
2291 bool BufferParams::hasClassDefaults() const
2293 DocumentClass const & tclass = documentClass();
2295 return sides == tclass.sides()
2296 && columns == tclass.columns()
2297 && pagestyle == tclass.pagestyle()
2298 && use_default_options
2299 && secnumdepth == tclass.secnumdepth()
2300 && tocdepth == tclass.tocdepth();
2304 DocumentClass const & BufferParams::documentClass() const
2310 DocumentClassConstPtr BufferParams::documentClassPtr() const
2316 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2318 // evil, but this function is evil
2319 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2320 invalidateConverterCache();
2324 bool BufferParams::setBaseClass(string const & classname)
2326 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2327 LayoutFileList & bcl = LayoutFileList::get();
2328 if (!bcl.haveClass(classname)) {
2330 bformat(_("The layout file:\n"
2332 "could not be found. A default textclass with default\n"
2333 "layouts will be used. LyX will not be able to produce\n"
2335 from_utf8(classname));
2336 frontend::Alert::error(_("Document class not found"), s);
2337 bcl.addEmptyClass(classname);
2340 bool const success = bcl[classname].load();
2343 bformat(_("Due to some error in it, the layout file:\n"
2345 "could not be loaded. A default textclass with default\n"
2346 "layouts will be used. LyX will not be able to produce\n"
2348 from_utf8(classname));
2349 frontend::Alert::error(_("Could not load class"), s);
2350 bcl.addEmptyClass(classname);
2353 pimpl_->baseClass_ = classname;
2354 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2359 LayoutFile const * BufferParams::baseClass() const
2361 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2362 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2368 LayoutFileIndex const & BufferParams::baseClassID() const
2370 return pimpl_->baseClass_;
2374 void BufferParams::makeDocumentClass(bool const clone)
2379 invalidateConverterCache();
2380 LayoutModuleList mods;
2381 LayoutModuleList ces;
2382 LayoutModuleList::iterator it = layout_modules_.begin();
2383 LayoutModuleList::iterator en = layout_modules_.end();
2384 for (; it != en; ++it)
2385 mods.push_back(*it);
2387 it = cite_engine_.begin();
2388 en = cite_engine_.end();
2389 for (; it != en; ++it)
2392 doc_class_ = getDocumentClass(*baseClass(), mods, ces, clone);
2394 TextClass::ReturnValues success = TextClass::OK;
2395 if (!forced_local_layout_.empty())
2396 success = doc_class_->read(to_utf8(forced_local_layout_),
2398 if (!local_layout_.empty() &&
2399 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2400 success = doc_class_->read(to_utf8(local_layout_), TextClass::MODULE);
2401 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2402 docstring const msg = _("Error reading internal layout information");
2403 frontend::Alert::warning(_("Read Error"), msg);
2408 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2410 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2414 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2416 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2420 docstring BufferParams::getLocalLayout(bool forced) const
2423 return from_utf8(doc_class_->forcedLayouts());
2425 return local_layout_;
2429 void BufferParams::setLocalLayout(docstring const & layout, bool forced)
2432 forced_local_layout_ = layout;
2434 local_layout_ = layout;
2438 bool BufferParams::addLayoutModule(string const & modName)
2440 LayoutModuleList::const_iterator it = layout_modules_.begin();
2441 LayoutModuleList::const_iterator end = layout_modules_.end();
2442 for (; it != end; ++it)
2445 layout_modules_.push_back(modName);
2450 string BufferParams::bufferFormat() const
2452 return documentClass().outputFormat();
2456 bool BufferParams::isExportable(string const & format, bool need_viewable) const
2458 FormatList const & formats = exportableFormats(need_viewable);
2459 FormatList::const_iterator fit = formats.begin();
2460 FormatList::const_iterator end = formats.end();
2461 for (; fit != end ; ++fit) {
2462 if ((*fit)->name() == format)
2469 FormatList const & BufferParams::exportableFormats(bool only_viewable) const
2471 FormatList & cached = only_viewable ?
2472 pimpl_->viewableFormatList : pimpl_->exportableFormatList;
2473 bool & valid = only_viewable ?
2474 pimpl_->isViewCacheValid : pimpl_->isExportCacheValid;
2478 vector<string> const backs = backends();
2479 set<string> excludes;
2480 if (useNonTeXFonts) {
2481 excludes.insert("latex");
2482 excludes.insert("pdflatex");
2485 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2486 for (vector<string>::const_iterator it = backs.begin() + 1;
2487 it != backs.end(); ++it) {
2488 FormatList r = theConverters().getReachable(*it, only_viewable,
2490 result.insert(result.end(), r.begin(), r.end());
2492 sort(result.begin(), result.end(), Format::formatSorter);
2499 vector<string> BufferParams::backends() const
2502 string const buffmt = bufferFormat();
2504 // FIXME: Don't hardcode format names here, but use a flag
2505 if (buffmt == "latex") {
2506 if (encoding().package() == Encoding::japanese)
2507 v.push_back("platex");
2509 if (!useNonTeXFonts) {
2510 v.push_back("pdflatex");
2511 v.push_back("latex");
2513 v.push_back("xetex");
2514 v.push_back("luatex");
2515 v.push_back("dviluatex");
2518 v.push_back(buffmt);
2520 v.push_back("xhtml");
2521 v.push_back("text");
2527 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2529 string const dformat = (format.empty() || format == "default") ?
2530 getDefaultOutputFormat() : format;
2531 DefaultFlavorCache::const_iterator it =
2532 default_flavors_.find(dformat);
2534 if (it != default_flavors_.end())
2537 OutputParams::FLAVOR result = OutputParams::LATEX;
2539 // FIXME It'd be better not to hardcode this, but to do
2540 // something with formats.
2541 if (dformat == "xhtml")
2542 result = OutputParams::HTML;
2543 else if (dformat == "text")
2544 result = OutputParams::TEXT;
2545 else if (dformat == "lyx")
2546 result = OutputParams::LYX;
2547 else if (dformat == "pdflatex")
2548 result = OutputParams::PDFLATEX;
2549 else if (dformat == "xetex")
2550 result = OutputParams::XETEX;
2551 else if (dformat == "luatex")
2552 result = OutputParams::LUATEX;
2553 else if (dformat == "dviluatex")
2554 result = OutputParams::DVILUATEX;
2556 // Try to determine flavor of default output format
2557 vector<string> backs = backends();
2558 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2559 // Get shortest path to format
2560 Graph::EdgePath path;
2561 for (vector<string>::const_iterator it = backs.begin();
2562 it != backs.end(); ++it) {
2563 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2564 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2569 result = theConverters().getFlavor(path);
2572 // cache this flavor
2573 default_flavors_[dformat] = result;
2578 string BufferParams::getDefaultOutputFormat() const
2580 if (!default_output_format.empty()
2581 && default_output_format != "default")
2582 return default_output_format;
2584 || encoding().package() == Encoding::japanese) {
2585 FormatList const & formats = exportableFormats(true);
2586 if (formats.empty())
2588 // return the first we find
2589 return formats.front()->name();
2592 return lyxrc.default_otf_view_format;
2593 return lyxrc.default_view_format;
2596 Font const BufferParams::getFont() const
2598 FontInfo f = documentClass().defaultfont();
2599 if (fonts_default_family == "rmdefault")
2600 f.setFamily(ROMAN_FAMILY);
2601 else if (fonts_default_family == "sfdefault")
2602 f.setFamily(SANS_FAMILY);
2603 else if (fonts_default_family == "ttdefault")
2604 f.setFamily(TYPEWRITER_FAMILY);
2605 return Font(f, language);
2609 InsetQuotesParams::QuoteStyle BufferParams::getQuoteStyle(string const & qs) const
2611 return quotesstyletranslator().find(qs);
2615 bool BufferParams::isLatex() const
2617 return documentClass().outputType() == LATEX;
2621 bool BufferParams::isLiterate() const
2623 return documentClass().outputType() == LITERATE;
2627 bool BufferParams::isDocBook() const
2629 return documentClass().outputType() == DOCBOOK;
2633 void BufferParams::readPreamble(Lexer & lex)
2635 if (lex.getString() != "\\begin_preamble")
2636 lyxerr << "Error (BufferParams::readPreamble):"
2637 "consistency check failed." << endl;
2639 preamble = lex.getLongString(from_ascii("\\end_preamble"));
2643 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2645 string const expected = forced ? "\\begin_forced_local_layout" :
2646 "\\begin_local_layout";
2647 if (lex.getString() != expected)
2648 lyxerr << "Error (BufferParams::readLocalLayout):"
2649 "consistency check failed." << endl;
2652 forced_local_layout_ =
2653 lex.getLongString(from_ascii("\\end_forced_local_layout"));
2655 local_layout_ = lex.getLongString(from_ascii("\\end_local_layout"));
2659 bool BufferParams::setLanguage(string const & lang)
2661 Language const *new_language = languages.getLanguage(lang);
2662 if (!new_language) {
2663 // Language lang was not found
2666 language = new_language;
2671 void BufferParams::readLanguage(Lexer & lex)
2673 if (!lex.next()) return;
2675 string const tmptok = lex.getString();
2677 // check if tmptok is part of tex_babel in tex-defs.h
2678 if (!setLanguage(tmptok)) {
2679 // Language tmptok was not found
2680 language = default_language;
2681 lyxerr << "Warning: Setting language `"
2682 << tmptok << "' to `" << language->lang()
2688 void BufferParams::readGraphicsDriver(Lexer & lex)
2693 string const tmptok = lex.getString();
2694 // check if tmptok is part of tex_graphics in tex_defs.h
2697 string const test = tex_graphics[n++];
2699 if (test == tmptok) {
2700 graphics_driver = tmptok;
2705 "Warning: graphics driver `$$Token' not recognized!\n"
2706 " Setting graphics driver to `default'.\n");
2707 graphics_driver = "default";
2714 void BufferParams::readBullets(Lexer & lex)
2719 int const index = lex.getInteger();
2721 int temp_int = lex.getInteger();
2722 user_defined_bullet(index).setFont(temp_int);
2723 temp_bullet(index).setFont(temp_int);
2725 user_defined_bullet(index).setCharacter(temp_int);
2726 temp_bullet(index).setCharacter(temp_int);
2728 user_defined_bullet(index).setSize(temp_int);
2729 temp_bullet(index).setSize(temp_int);
2733 void BufferParams::readBulletsLaTeX(Lexer & lex)
2735 // The bullet class should be able to read this.
2738 int const index = lex.getInteger();
2740 docstring const temp_str = lex.getDocString();
2742 user_defined_bullet(index).setText(temp_str);
2743 temp_bullet(index).setText(temp_str);
2747 void BufferParams::readModules(Lexer & lex)
2749 if (!lex.eatLine()) {
2750 lyxerr << "Error (BufferParams::readModules):"
2751 "Unexpected end of input." << endl;
2755 string mod = lex.getString();
2756 if (mod == "\\end_modules")
2758 addLayoutModule(mod);
2764 void BufferParams::readRemovedModules(Lexer & lex)
2766 if (!lex.eatLine()) {
2767 lyxerr << "Error (BufferParams::readRemovedModules):"
2768 "Unexpected end of input." << endl;
2772 string mod = lex.getString();
2773 if (mod == "\\end_removed_modules")
2775 removed_modules_.push_back(mod);
2778 // now we want to remove any removed modules that were previously
2779 // added. normally, that will be because default modules were added in
2780 // setBaseClass(), which gets called when \textclass is read at the
2781 // start of the read.
2782 list<string>::const_iterator rit = removed_modules_.begin();
2783 list<string>::const_iterator const ren = removed_modules_.end();
2784 for (; rit != ren; ++rit) {
2785 LayoutModuleList::iterator const mit = layout_modules_.begin();
2786 LayoutModuleList::iterator const men = layout_modules_.end();
2787 LayoutModuleList::iterator found = find(mit, men, *rit);
2790 layout_modules_.erase(found);
2795 void BufferParams::readIncludeonly(Lexer & lex)
2797 if (!lex.eatLine()) {
2798 lyxerr << "Error (BufferParams::readIncludeonly):"
2799 "Unexpected end of input." << endl;
2803 string child = lex.getString();
2804 if (child == "\\end_includeonly")
2806 included_children_.push_back(child);
2812 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2814 switch (papersize) {
2816 // could be anything, so don't guess
2818 case PAPER_CUSTOM: {
2819 if (purpose == XDVI && !paperwidth.empty() &&
2820 !paperheight.empty()) {
2821 // heightxwidth<unit>
2822 string first = paperwidth;
2823 string second = paperheight;
2824 if (orientation == ORIENTATION_LANDSCAPE)
2827 return first.erase(first.length() - 2)
2833 // dvips and dvipdfm do not know this
2834 if (purpose == DVIPS || purpose == DVIPDFM)
2838 if (purpose == DVIPS || purpose == DVIPDFM)
2842 if (purpose == DVIPS || purpose == DVIPDFM)
2852 if (purpose == DVIPS || purpose == DVIPDFM)
2856 if (purpose == DVIPS || purpose == DVIPDFM)
2860 if (purpose == DVIPS || purpose == DVIPDFM)
2864 if (purpose == DVIPS || purpose == DVIPDFM)
2868 if (purpose == DVIPS || purpose == DVIPDFM)
2872 // dvipdfm does not know this
2873 if (purpose == DVIPDFM)
2877 if (purpose == DVIPDFM)
2881 if (purpose == DVIPS || purpose == DVIPDFM)
2885 if (purpose == DVIPS || purpose == DVIPDFM)
2889 if (purpose == DVIPS || purpose == DVIPDFM)
2893 if (purpose == DVIPS || purpose == DVIPDFM)
2897 if (purpose == DVIPS || purpose == DVIPDFM)
2901 if (purpose == DVIPS || purpose == DVIPDFM)
2905 if (purpose == DVIPS || purpose == DVIPDFM)
2909 if (purpose == DVIPS || purpose == DVIPDFM)
2913 if (purpose == DVIPS || purpose == DVIPDFM)
2917 if (purpose == DVIPS || purpose == DVIPDFM)
2921 if (purpose == DVIPS || purpose == DVIPDFM)
2925 if (purpose == DVIPS || purpose == DVIPDFM)
2929 if (purpose == DVIPS || purpose == DVIPDFM)
2933 if (purpose == DVIPS || purpose == DVIPDFM)
2937 if (purpose == DVIPS || purpose == DVIPDFM)
2940 case PAPER_USEXECUTIVE:
2941 // dvipdfm does not know this
2942 if (purpose == DVIPDFM)
2947 case PAPER_USLETTER:
2949 if (purpose == XDVI)
2956 string const BufferParams::dvips_options() const
2960 // If the class loads the geometry package, we do not know which
2961 // paper size is used, since we do not set it (bug 7013).
2962 // Therefore we must not specify any argument here.
2963 // dvips gets the correct paper size via DVI specials in this case
2964 // (if the class uses the geometry package correctly).
2965 if (documentClass().provides("geometry"))
2969 && papersize == PAPER_CUSTOM
2970 && !lyxrc.print_paper_dimension_flag.empty()
2971 && !paperwidth.empty()
2972 && !paperheight.empty()) {
2973 // using a custom papersize
2974 result = lyxrc.print_paper_dimension_flag;
2975 result += ' ' + paperwidth;
2976 result += ',' + paperheight;
2978 string const paper_option = paperSizeName(DVIPS);
2979 if (!paper_option.empty() && (paper_option != "letter" ||
2980 orientation != ORIENTATION_LANDSCAPE)) {
2981 // dvips won't accept -t letter -t landscape.
2982 // In all other cases, include the paper size
2984 result = lyxrc.print_paper_flag;
2985 result += ' ' + paper_option;
2988 if (orientation == ORIENTATION_LANDSCAPE &&
2989 papersize != PAPER_CUSTOM)
2990 result += ' ' + lyxrc.print_landscape_flag;
2995 string const BufferParams::main_font_encoding() const
2997 return font_encodings().empty() ? "default" : font_encodings().back();
3001 vector<string> const BufferParams::font_encodings() const
3003 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
3005 vector<string> fontencs;
3007 // "default" means "no explicit font encoding"
3008 if (doc_fontenc != "default") {
3009 fontencs = getVectorFromString(doc_fontenc);
3010 if (!language->fontenc().empty()
3011 && ascii_lowercase(language->fontenc()) != "none") {
3012 vector<string> fencs = getVectorFromString(language->fontenc());
3013 vector<string>::const_iterator fit = fencs.begin();
3014 for (; fit != fencs.end(); ++fit) {
3015 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
3016 fontencs.push_back(*fit);
3025 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
3027 // suppress the babel call if there is no BabelName defined
3028 // for the document language in the lib/languages file and if no
3029 // other languages are used (lang_opts is then empty)
3030 if (lang_opts.empty())
3032 // either a specific language (AsBabelOptions setting in
3033 // lib/languages) or the prefs require the languages to
3034 // be submitted to babel itself (not the class).
3036 return "\\usepackage[" + lang_opts + "]{babel}";
3037 return "\\usepackage{babel}";
3041 docstring BufferParams::getGraphicsDriver(string const & package) const
3045 if (package == "geometry") {
3046 if (graphics_driver == "dvips"
3047 || graphics_driver == "dvipdfm"
3048 || graphics_driver == "pdftex"
3049 || graphics_driver == "vtex")
3050 result = from_ascii(graphics_driver);
3051 else if (graphics_driver == "dvipdfmx")
3052 result = from_ascii("dvipdfm");
3059 void BufferParams::writeEncodingPreamble(otexstream & os,
3060 LaTeXFeatures & features) const
3062 // XeTeX/LuaTeX: (see also #9740)
3063 // With Unicode fonts we use utf8-plain without encoding package.
3064 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
3065 // XeTeX must use ASCII encoding (see Buffer.cpp),
3066 // for LuaTeX, we load "luainputenc" (see below).
3067 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
3070 if (inputenc == "auto") {
3071 string const doc_encoding =
3072 language->encoding()->latexName();
3073 Encoding::Package const package =
3074 language->encoding()->package();
3076 // Create list of inputenc options:
3077 set<string> encodings;
3078 // luainputenc fails with more than one encoding
3079 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
3080 // list all input encodings used in the document
3081 encodings = features.getEncodingSet(doc_encoding);
3083 // If the "japanese" package (i.e. pLaTeX) is used,
3084 // inputenc must be omitted.
3085 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
3086 if ((!encodings.empty() || package == Encoding::inputenc)
3087 && !features.isRequired("japanese")
3088 && !features.isProvided("inputenc")) {
3089 os << "\\usepackage[";
3090 set<string>::const_iterator it = encodings.begin();
3091 set<string>::const_iterator const end = encodings.end();
3093 os << from_ascii(*it);
3096 for (; it != end; ++it)
3097 os << ',' << from_ascii(*it);
3098 if (package == Encoding::inputenc) {
3099 if (!encodings.empty())
3101 os << from_ascii(doc_encoding);
3103 if (features.runparams().flavor == OutputParams::LUATEX
3104 || features.runparams().flavor == OutputParams::DVILUATEX)
3105 os << "]{luainputenc}\n";
3107 os << "]{inputenc}\n";
3109 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3110 if (language->encoding()->name() == "utf8-cjk"
3111 && LaTeXFeatures::isAvailable("CJKutf8"))
3112 os << "\\usepackage{CJKutf8}\n";
3114 os << "\\usepackage{CJK}\n";
3116 } else if (inputenc != "default") {
3117 switch (encoding().package()) {
3118 case Encoding::none:
3119 case Encoding::japanese:
3121 case Encoding::inputenc:
3122 // do not load inputenc if japanese is used
3123 // or if the class provides inputenc
3124 if (features.isRequired("japanese")
3125 || features.isProvided("inputenc"))
3127 os << "\\usepackage[" << from_ascii(encoding().latexName());
3128 if (features.runparams().flavor == OutputParams::LUATEX
3129 || features.runparams().flavor == OutputParams::DVILUATEX)
3130 os << "]{luainputenc}\n";
3132 os << "]{inputenc}\n";
3135 if (encoding().name() == "utf8-cjk"
3136 && LaTeXFeatures::isAvailable("CJKutf8"))
3137 os << "\\usepackage{CJKutf8}\n";
3139 os << "\\usepackage{CJK}\n";
3142 // Load the CJK package if needed by a secondary language.
3143 // If the main encoding is some variant of UTF8, use CJKutf8.
3144 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3145 if (encoding().iconvName() == "UTF-8"
3146 && LaTeXFeatures::isAvailable("CJKutf8"))
3147 os << "\\usepackage{CJKutf8}\n";
3149 os << "\\usepackage{CJK}\n";
3155 string const BufferParams::parseFontName(string const & name) const
3157 string mangled = name;
3158 size_t const idx = mangled.find('[');
3159 if (idx == string::npos || idx == 0)
3162 return mangled.substr(0, idx - 1);
3166 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3168 if (fontsRoman() == "default" && fontsSans() == "default"
3169 && fontsTypewriter() == "default"
3170 && (fontsMath() == "default" || fontsMath() == "auto"))
3176 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3177 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3178 * Mapping=tex-text option assures TeX ligatures (such as "--")
3179 * are resolved. Note that tt does not use these ligatures.
3181 * -- add more GUI options?
3182 * -- add more fonts (fonts for other scripts)
3183 * -- if there's a way to find out if a font really supports
3184 * OldStyle, enable/disable the widget accordingly.
3186 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3187 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3188 // However, until v.2 (2010/07/11) fontspec only knew
3189 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3190 // was introduced for both XeTeX and LuaTeX (LuaTeX
3191 // didn't understand "Mapping=tex-text", while XeTeX
3192 // understood both. With most recent versions, both
3193 // variants are understood by both engines. However,
3194 // we want to provide support for at least TeXLive 2009
3195 // (for XeTeX; LuaTeX is only supported as of v.2)
3196 string const texmapping =
3197 (features.runparams().flavor == OutputParams::XETEX) ?
3198 "Mapping=tex-text" : "Ligatures=TeX";
3199 if (fontsRoman() != "default") {
3200 os << "\\setmainfont[" << texmapping;
3201 if (fonts_old_figures)
3202 os << ",Numbers=OldStyle";
3203 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3205 if (fontsSans() != "default") {
3206 string const sans = parseFontName(fontsSans());
3207 if (fontsSansScale() != 100)
3208 os << "\\setsansfont[Scale="
3209 << float(fontsSansScale()) / 100
3210 << "," << texmapping << "]{"
3213 os << "\\setsansfont[" << texmapping << "]{"
3216 if (fontsTypewriter() != "default") {
3217 string const mono = parseFontName(fontsTypewriter());
3218 if (fontsTypewriterScale() != 100)
3219 os << "\\setmonofont[Scale="
3220 << float(fontsTypewriterScale()) / 100
3224 os << "\\setmonofont{"
3231 bool const ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1");
3232 bool const dryrun = features.runparams().dryrun;
3233 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3234 bool const nomath = (fontsMath() == "default");
3237 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3238 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3242 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3243 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3244 nomath, fontsSansScale());
3246 // MONOSPACED/TYPEWRITER
3247 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3248 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3249 nomath, fontsTypewriterScale());
3252 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3253 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3260 Encoding const & BufferParams::encoding() const
3262 // Main encoding for LaTeX output.
3264 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3265 // As the "flavor" is only known once export started, this
3266 // cannot be handled here. Instead, runparams.encoding is set
3267 // to ASCII in Buffer::makeLaTeXFile (for export)
3268 // and Buffer::writeLaTeXSource (for preview).
3270 return *(encodings.fromLyXName("utf8-plain"));
3271 if (inputenc == "auto" || inputenc == "default")
3272 return *language->encoding();
3273 Encoding const * const enc = encodings.fromLyXName(inputenc);
3276 LYXERR0("Unknown inputenc value `" << inputenc
3277 << "'. Using `auto' instead.");
3278 return *language->encoding();
3282 bool BufferParams::addCiteEngine(string const & engine)
3284 LayoutModuleList::const_iterator it = cite_engine_.begin();
3285 LayoutModuleList::const_iterator en = cite_engine_.end();
3286 for (; it != en; ++it)
3289 cite_engine_.push_back(engine);
3294 bool BufferParams::addCiteEngine(vector<string> const & engine)
3296 vector<string>::const_iterator it = engine.begin();
3297 vector<string>::const_iterator en = engine.end();
3299 for (; it != en; ++it)
3300 if (!addCiteEngine(*it))
3306 string const & BufferParams::defaultBiblioStyle() const
3308 map<string, string> bs = documentClass().defaultBiblioStyle();
3309 return bs[theCiteEnginesList.getTypeAsString(citeEngineType())];
3313 bool const & BufferParams::fullAuthorList() const
3315 return documentClass().fullAuthorList();
3319 string BufferParams::getCiteAlias(string const & s) const
3321 vector<string> commands =
3322 documentClass().citeCommands(citeEngineType());
3323 // If it is a real command, don't treat it as an alias
3324 if (find(commands.begin(), commands.end(), s) != commands.end())
3326 map<string,string> aliases = documentClass().citeCommandAliases();
3327 if (aliases.find(s) != aliases.end())
3333 void BufferParams::setCiteEngine(string const & engine)
3336 addCiteEngine(engine);
3340 void BufferParams::setCiteEngine(vector<string> const & engine)
3343 addCiteEngine(engine);
3347 vector<string> BufferParams::citeCommands() const
3349 static CitationStyle const default_style;
3350 vector<string> commands =
3351 documentClass().citeCommands(citeEngineType());
3352 if (commands.empty())
3353 commands.push_back(default_style.name);
3358 vector<CitationStyle> BufferParams::citeStyles() const
3360 static CitationStyle const default_style;
3361 vector<CitationStyle> styles =
3362 documentClass().citeStyles(citeEngineType());
3364 styles.push_back(default_style);
3369 string const BufferParams::bibtexCommand() const
3371 // Return document-specific setting if available
3372 if (bibtex_command != "default")
3373 return bibtex_command;
3375 // If we have "default" in document settings, consult the prefs
3376 // 1. Japanese (uses a specific processor)
3377 if (encoding().package() == Encoding::japanese) {
3378 if (lyxrc.jbibtex_command != "automatic")
3379 // Return the specified program, if "automatic" is not set
3380 return lyxrc.jbibtex_command;
3381 else if (!useBiblatex()) {
3382 // With classic BibTeX, return pbibtex, jbibtex, bibtex
3383 if (lyxrc.jbibtex_alternatives.find("pbibtex") != lyxrc.jbibtex_alternatives.end())
3385 if (lyxrc.jbibtex_alternatives.find("jbibtex") != lyxrc.jbibtex_alternatives.end())
3390 // 2. All other languages
3391 else if (lyxrc.bibtex_command != "automatic")
3392 // Return the specified program, if "automatic" is not set
3393 return lyxrc.bibtex_command;
3395 // 3. Automatic: find the most suitable for the current cite framework
3396 if (useBiblatex()) {
3397 // For Biblatex, we prefer biber (also for Japanese)
3398 // and fall back to bibtex8 and, as last resort, bibtex
3399 if (lyxrc.bibtex_alternatives.find("biber") != lyxrc.bibtex_alternatives.end())
3401 else if (lyxrc.bibtex_alternatives.find("bibtex8") != lyxrc.bibtex_alternatives.end())
3408 bool BufferParams::useBiblatex() const
3410 return theCiteEnginesList[citeEngine().list().front()]
3411 ->getCiteFramework() == "biblatex";
3415 void BufferParams::invalidateConverterCache() const
3417 pimpl_->isExportCacheValid = false;
3418 pimpl_->isViewCacheValid = false;