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;
341 /** This is the amount of space used for paragraph_separation "skip",
342 * and for detached paragraphs in "indented" documents.
345 PDFOptions pdfoptions;
346 LayoutFileIndex baseClass_;
347 FormatList exportableFormatList;
348 FormatList viewableFormatList;
349 bool isViewCacheValid;
350 bool isExportCacheValid;
354 BufferParams::Impl::Impl()
355 : defskip(VSpace::MEDSKIP), baseClass_(string("")),
356 isViewCacheValid(false), isExportCacheValid(false)
358 // set initial author
360 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
365 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
368 return new BufferParams::Impl(*ptr);
372 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
378 BufferParams::BufferParams()
381 setBaseClass(defaultBaseclass());
382 cite_engine_.push_back("basic");
383 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
385 paragraph_separation = ParagraphIndentSeparation;
386 is_math_indent = false;
387 math_indentation = "default";
388 quotes_style = InsetQuotesParams::EnglishQuotes;
389 dynamic_quotes = false;
390 fontsize = "default";
393 papersize = PAPER_DEFAULT;
394 orientation = ORIENTATION_PORTRAIT;
395 use_geometry = false;
396 biblio_style = "plain";
397 use_bibtopic = false;
400 save_transient_properties = true;
401 track_changes = false;
402 output_changes = false;
403 use_default_options = true;
404 maintain_unincluded_children = false;
407 language = default_language;
409 fonts_roman[0] = "default";
410 fonts_roman[1] = "default";
411 fonts_sans[0] = "default";
412 fonts_sans[1] = "default";
413 fonts_typewriter[0] = "default";
414 fonts_typewriter[1] = "default";
415 fonts_math[0] = "auto";
416 fonts_math[1] = "auto";
417 fonts_default_family = "default";
418 useNonTeXFonts = false;
419 use_microtype = false;
420 use_dash_ligatures = true;
421 fonts_expert_sc = false;
422 fonts_old_figures = false;
423 fonts_sans_scale[0] = 100;
424 fonts_sans_scale[1] = 100;
425 fonts_typewriter_scale[0] = 100;
426 fonts_typewriter_scale[1] = 100;
428 lang_package = "default";
429 graphics_driver = "default";
430 default_output_format = "default";
431 bibtex_command = "default";
432 index_command = "default";
435 listings_params = string();
436 pagestyle = "default";
437 suppress_date = false;
438 justification = true;
439 // no color is the default (white)
440 backgroundcolor = lyx::rgbFromHexName("#ffffff");
441 isbackgroundcolor = false;
442 // no color is the default (black)
443 fontcolor = lyx::rgbFromHexName("#000000");
445 // light gray is the default font color for greyed-out notes
446 notefontcolor = lyx::rgbFromHexName("#cccccc");
447 boxbgcolor = lyx::rgbFromHexName("#ff0000");
448 compressed = lyxrc.save_compressed;
449 for (int iter = 0; iter < 4; ++iter) {
450 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
451 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
454 indiceslist().addDefault(B_("Index"));
455 html_be_strict = false;
456 html_math_output = MathML;
457 html_math_img_scale = 1.0;
458 html_css_as_file = false;
459 display_pixel_ratio = 1.0;
464 // map current author
465 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
469 docstring BufferParams::B_(string const & l10n) const
471 LASSERT(language, return from_utf8(l10n));
472 return getMessages(language->code()).get(l10n);
476 BufferParams::Package BufferParams::use_package(std::string const & p) const
478 PackageMap::const_iterator it = use_packages.find(p);
479 if (it == use_packages.end())
485 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
491 map<string, string> const & BufferParams::auto_packages()
493 static map<string, string> packages;
494 if (packages.empty()) {
495 // We could have a race condition here that two threads
496 // discover an empty map at the same time and want to fill
497 // it, but that is no problem, since the same contents is
498 // filled in twice then. Having the locker inside the
499 // packages.empty() condition has the advantage that we
500 // don't need the mutex overhead for simple reading.
502 Mutex::Locker locker(&mutex);
503 // adding a package here implies a file format change!
504 packages["amsmath"] =
505 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
506 packages["amssymb"] =
507 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
509 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
511 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
512 packages["mathdots"] =
513 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
514 packages["mathtools"] =
515 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
517 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
518 packages["stackrel"] =
519 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
520 packages["stmaryrd"] =
521 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");
522 packages["undertilde"] =
523 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
529 bool BufferParams::useBibtopic() const
533 return (use_bibtopic || (!multibib.empty() && multibib != "child"));
537 AuthorList & BufferParams::authors()
539 return pimpl_->authorlist;
543 AuthorList const & BufferParams::authors() const
545 return pimpl_->authorlist;
549 void BufferParams::addAuthor(Author a)
551 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
555 BranchList & BufferParams::branchlist()
557 return pimpl_->branchlist;
561 BranchList const & BufferParams::branchlist() const
563 return pimpl_->branchlist;
567 IndicesList & BufferParams::indiceslist()
569 return pimpl_->indiceslist;
573 IndicesList const & BufferParams::indiceslist() const
575 return pimpl_->indiceslist;
579 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
581 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
582 return pimpl_->temp_bullets[index];
586 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
588 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
589 return pimpl_->temp_bullets[index];
593 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
595 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
596 return pimpl_->user_defined_bullets[index];
600 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
602 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
603 return pimpl_->user_defined_bullets[index];
607 Spacing & BufferParams::spacing()
609 return pimpl_->spacing;
613 Spacing const & BufferParams::spacing() const
615 return pimpl_->spacing;
619 PDFOptions & BufferParams::pdfoptions()
621 return pimpl_->pdfoptions;
625 PDFOptions const & BufferParams::pdfoptions() const
627 return pimpl_->pdfoptions;
631 Length const & BufferParams::getParIndent() const
633 return pimpl_->parindent;
637 void BufferParams::setParIndent(Length const & indent)
639 pimpl_->parindent = indent;
643 VSpace const & BufferParams::getDefSkip() const
645 return pimpl_->defskip;
649 void BufferParams::setDefSkip(VSpace const & vs)
651 // DEFSKIP will cause an infinite loop
652 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
653 pimpl_->defskip = vs;
657 string BufferParams::readToken(Lexer & lex, string const & token,
658 FileName const & filepath)
662 if (token == "\\textclass") {
664 string const classname = lex.getString();
665 // if there exists a local layout file, ignore the system one
666 // NOTE: in this case, the textclass (.cls file) is assumed to
669 LayoutFileList & bcl = LayoutFileList::get();
670 if (!filepath.empty()) {
671 // If classname is an absolute path, the document is
672 // using a local layout file which could not be accessed
673 // by a relative path. In this case the path is correct
674 // even if the document was moved to a different
675 // location. However, we will have a problem if the
676 // document was generated on a different platform.
677 bool isabsolute = FileName::isAbsolute(classname);
678 string const classpath = onlyPath(classname);
679 string const path = isabsolute ? classpath
680 : FileName(addPath(filepath.absFileName(),
681 classpath)).realPath();
682 string const oldpath = isabsolute ? string()
683 : FileName(addPath(origin, classpath)).realPath();
684 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
686 // that returns non-empty if a "local" layout file is found.
688 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
689 from_utf8(filepath.absFileName())));
692 setBaseClass(onlyFileName(tcp));
694 setBaseClass(onlyFileName(classname));
695 // We assume that a tex class exists for local or unknown
696 // layouts so this warning, will only be given for system layouts.
697 if (!baseClass()->isTeXClassAvailable()) {
698 docstring const desc =
699 translateIfPossible(from_utf8(baseClass()->description()));
700 docstring const prereqs =
701 from_utf8(baseClass()->prerequisites());
702 docstring const msg =
703 bformat(_("The selected document class\n"
705 "requires external files that are not available.\n"
706 "The document class can still be used, but the\n"
707 "document cannot be compiled until the following\n"
708 "prerequisites are installed:\n"
710 "See section 3.1.2.2 (Class Availability) of the\n"
711 "User's Guide for more information."), desc, prereqs);
712 frontend::Alert::warning(_("Document class not available"),
715 } else if (token == "\\save_transient_properties") {
716 lex >> save_transient_properties;
717 } else if (token == "\\origin") {
719 origin = lex.getString();
720 string const sysdirprefix = "/systemlyxdir/";
721 if (prefixIs(origin, sysdirprefix)) {
723 if (inSystemDir(filepath, docsys))
724 origin.replace(0, sysdirprefix.length() - 1, docsys);
726 origin.replace(0, sysdirprefix.length() - 1,
727 package().system_support().absFileName());
729 } else if (token == "\\begin_preamble") {
731 } else if (token == "\\begin_local_layout") {
732 readLocalLayout(lex, false);
733 } else if (token == "\\begin_forced_local_layout") {
734 readLocalLayout(lex, true);
735 } else if (token == "\\begin_modules") {
737 } else if (token == "\\begin_removed_modules") {
738 readRemovedModules(lex);
739 } else if (token == "\\begin_includeonly") {
740 readIncludeonly(lex);
741 } else if (token == "\\maintain_unincluded_children") {
742 lex >> maintain_unincluded_children;
743 } else if (token == "\\options") {
745 options = lex.getString();
746 } else if (token == "\\use_default_options") {
747 lex >> use_default_options;
748 } else if (token == "\\master") {
750 master = lex.getString();
751 if (!filepath.empty() && FileName::isAbsolute(origin)) {
752 bool const isabs = FileName::isAbsolute(master);
753 FileName const abspath(isabs ? master : origin + master);
754 bool const moved = filepath != FileName(origin);
755 if (moved && abspath.exists()) {
756 docstring const path = isabs
758 : from_utf8(abspath.realPath());
759 docstring const refpath =
760 from_utf8(filepath.absFileName());
761 master = to_utf8(makeRelPath(path, refpath));
764 } else if (token == "\\suppress_date") {
765 lex >> suppress_date;
766 } else if (token == "\\justification") {
767 lex >> justification;
768 } else if (token == "\\language") {
770 } else if (token == "\\language_package") {
772 lang_package = lex.getString();
773 } else if (token == "\\inputencoding") {
775 } else if (token == "\\graphics") {
776 readGraphicsDriver(lex);
777 } else if (token == "\\default_output_format") {
778 lex >> default_output_format;
779 } else if (token == "\\bibtex_command") {
781 bibtex_command = lex.getString();
782 } else if (token == "\\index_command") {
784 index_command = lex.getString();
785 } else if (token == "\\fontencoding") {
787 fontenc = lex.getString();
788 } else if (token == "\\font_roman") {
789 lex >> fonts_roman[0];
790 lex >> fonts_roman[1];
791 } else if (token == "\\font_sans") {
792 lex >> fonts_sans[0];
793 lex >> fonts_sans[1];
794 } else if (token == "\\font_typewriter") {
795 lex >> fonts_typewriter[0];
796 lex >> fonts_typewriter[1];
797 } else if (token == "\\font_math") {
798 lex >> fonts_math[0];
799 lex >> fonts_math[1];
800 } else if (token == "\\font_default_family") {
801 lex >> fonts_default_family;
802 } else if (token == "\\use_non_tex_fonts") {
803 lex >> useNonTeXFonts;
804 } else if (token == "\\font_sc") {
805 lex >> fonts_expert_sc;
806 } else if (token == "\\font_osf") {
807 lex >> fonts_old_figures;
808 } else if (token == "\\font_sf_scale") {
809 lex >> fonts_sans_scale[0];
810 lex >> fonts_sans_scale[1];
811 } else if (token == "\\font_tt_scale") {
812 lex >> fonts_typewriter_scale[0];
813 lex >> fonts_typewriter_scale[1];
814 } else if (token == "\\font_cjk") {
816 } else if (token == "\\use_microtype") {
817 lex >> use_microtype;
818 } else if (token == "\\use_dash_ligatures") {
819 lex >> use_dash_ligatures;
820 } else if (token == "\\paragraph_separation") {
823 paragraph_separation = parseptranslator().find(parsep);
824 } else if (token == "\\paragraph_indentation") {
826 string parindent = lex.getString();
827 if (parindent == "default")
828 pimpl_->parindent = Length();
830 pimpl_->parindent = Length(parindent);
831 } else if (token == "\\defskip") {
833 string const defskip = lex.getString();
834 pimpl_->defskip = VSpace(defskip);
835 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
837 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
838 } else if (token == "\\is_math_indent") {
839 lex >> is_math_indent;
840 } else if (token == "\\math_indentation") {
841 lex >> math_indentation;
842 } else if (token == "\\quotes_style") {
845 quotes_style = quotesstyletranslator().find(qstyle);
846 } else if (token == "\\dynamic_quotes") {
847 lex >> dynamic_quotes;
848 } else if (token == "\\papersize") {
851 papersize = papersizetranslator().find(ppsize);
852 } else if (token == "\\use_geometry") {
854 } else if (token == "\\use_package") {
859 use_package(package, packagetranslator().find(use));
860 } else if (token == "\\cite_engine") {
862 vector<string> engine = getVectorFromString(lex.getString());
863 setCiteEngine(engine);
864 } else if (token == "\\cite_engine_type") {
867 cite_engine_type_ = theCiteEnginesList.getType(engine_type);
868 } else if (token == "\\biblio_style") {
870 biblio_style = lex.getString();
871 } else if (token == "\\biblio_options") {
873 biblio_opts = trim(lex.getString());
874 } else if (token == "\\biblatex_bibstyle") {
876 biblatex_bibstyle = trim(lex.getString());
877 } else if (token == "\\biblatex_citestyle") {
879 biblatex_citestyle = trim(lex.getString());
880 } else if (token == "\\use_bibtopic") {
882 } else if (token == "\\multibib") {
884 } else if (token == "\\use_indices") {
886 } else if (token == "\\tracking_changes") {
887 lex >> track_changes;
888 } else if (token == "\\output_changes") {
889 lex >> output_changes;
890 } else if (token == "\\branch") {
892 docstring branch = lex.getDocString();
893 branchlist().add(branch);
896 string const tok = lex.getString();
897 if (tok == "\\end_branch")
899 Branch * branch_ptr = branchlist().find(branch);
900 if (tok == "\\selected") {
903 branch_ptr->setSelected(lex.getInteger());
905 if (tok == "\\filename_suffix") {
908 branch_ptr->setFileNameSuffix(lex.getInteger());
910 if (tok == "\\color") {
912 string color = lex.getString();
914 branch_ptr->setColor(color);
915 // Update also the Color table:
917 color = lcolor.getX11Name(Color_background);
919 lcolor.setColor(to_utf8(branch), color);
922 } else if (token == "\\index") {
924 docstring index = lex.getDocString();
926 indiceslist().add(index);
929 string const tok = lex.getString();
930 if (tok == "\\end_index")
932 Index * index_ptr = indiceslist().find(index);
933 if (tok == "\\shortcut") {
935 shortcut = lex.getDocString();
937 index_ptr->setShortcut(shortcut);
939 if (tok == "\\color") {
941 string color = lex.getString();
943 index_ptr->setColor(color);
944 // Update also the Color table:
946 color = lcolor.getX11Name(Color_background);
948 if (!shortcut.empty())
949 lcolor.setColor(to_utf8(shortcut), color);
952 } else if (token == "\\author") {
954 istringstream ss(lex.getString());
958 } else if (token == "\\paperorientation") {
961 orientation = paperorientationtranslator().find(orient);
962 } else if (token == "\\backgroundcolor") {
964 backgroundcolor = lyx::rgbFromHexName(lex.getString());
965 isbackgroundcolor = true;
966 } else if (token == "\\fontcolor") {
968 fontcolor = lyx::rgbFromHexName(lex.getString());
970 } else if (token == "\\notefontcolor") {
972 string color = lex.getString();
973 notefontcolor = lyx::rgbFromHexName(color);
974 lcolor.setColor("notefontcolor", color);
975 } else if (token == "\\boxbgcolor") {
977 string color = lex.getString();
978 boxbgcolor = lyx::rgbFromHexName(color);
979 lcolor.setColor("boxbgcolor", color);
980 } else if (token == "\\paperwidth") {
982 } else if (token == "\\paperheight") {
984 } else if (token == "\\leftmargin") {
986 } else if (token == "\\topmargin") {
988 } else if (token == "\\rightmargin") {
990 } else if (token == "\\bottommargin") {
992 } else if (token == "\\headheight") {
994 } else if (token == "\\headsep") {
996 } else if (token == "\\footskip") {
998 } else if (token == "\\columnsep") {
1000 } else if (token == "\\paperfontsize") {
1002 } else if (token == "\\papercolumns") {
1004 } else if (token == "\\listings_params") {
1007 listings_params = InsetListingsParams(par).params();
1008 } else if (token == "\\papersides") {
1011 sides = sidestranslator().find(psides);
1012 } else if (token == "\\paperpagestyle") {
1014 } else if (token == "\\bullet") {
1016 } else if (token == "\\bulletLaTeX") {
1017 readBulletsLaTeX(lex);
1018 } else if (token == "\\secnumdepth") {
1020 } else if (token == "\\tocdepth") {
1022 } else if (token == "\\spacing") {
1026 if (nspacing == "other") {
1029 spacing().set(spacetranslator().find(nspacing), tmp_val);
1030 } else if (token == "\\float_placement") {
1031 lex >> float_placement;
1033 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
1034 string toktmp = pdfoptions().readToken(lex, token);
1035 if (!toktmp.empty()) {
1036 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
1040 } else if (token == "\\html_math_output") {
1043 html_math_output = static_cast<MathOutput>(temp);
1044 } else if (token == "\\html_be_strict") {
1045 lex >> html_be_strict;
1046 } else if (token == "\\html_css_as_file") {
1047 lex >> html_css_as_file;
1048 } else if (token == "\\html_math_img_scale") {
1049 lex >> html_math_img_scale;
1050 } else if (token == "\\html_latex_start") {
1052 html_latex_start = lex.getString();
1053 } else if (token == "\\html_latex_end") {
1055 html_latex_end = lex.getString();
1056 } else if (token == "\\output_sync") {
1058 } else if (token == "\\output_sync_macro") {
1059 lex >> output_sync_macro;
1060 } else if (token == "\\use_refstyle") {
1061 lex >> use_refstyle;
1063 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1073 // Quote argument if it contains spaces
1074 string quoteIfNeeded(string const & str) {
1075 if (contains(str, ' '))
1076 return "\"" + str + "\"";
1082 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1084 // The top of the file is written by the buffer.
1085 // Prints out the buffer info into the .lyx file given by file
1087 os << "\\save_transient_properties "
1088 << convert<string>(save_transient_properties) << '\n';
1090 // the document directory (must end with a path separator)
1091 // realPath() is used to resolve symlinks, while addPath(..., "")
1092 // ensures a trailing path separator.
1094 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1095 string const sysdir = inSystemDir(FileName(filepath), docsys) ? docsys
1096 : addPath(package().system_support().realPath(), "");
1097 string const relpath =
1098 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1099 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1100 filepath = addPath("/systemlyxdir", relpath);
1101 else if (!save_transient_properties || !lyxrc.save_origin)
1102 filepath = "unavailable";
1103 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1106 os << "\\textclass "
1107 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1108 baseClass()->name()), "layout"))
1111 // then the preamble
1112 if (!preamble.empty()) {
1113 // remove '\n' from the end of preamble
1114 docstring const tmppreamble = rtrim(preamble, "\n");
1115 os << "\\begin_preamble\n"
1116 << to_utf8(tmppreamble)
1117 << "\n\\end_preamble\n";
1121 if (!options.empty()) {
1122 os << "\\options " << options << '\n';
1125 // use the class options defined in the layout?
1126 os << "\\use_default_options "
1127 << convert<string>(use_default_options) << "\n";
1129 // the master document
1130 if (!master.empty()) {
1131 os << "\\master " << master << '\n';
1135 if (!removed_modules_.empty()) {
1136 os << "\\begin_removed_modules" << '\n';
1137 list<string>::const_iterator it = removed_modules_.begin();
1138 list<string>::const_iterator en = removed_modules_.end();
1139 for (; it != en; ++it)
1141 os << "\\end_removed_modules" << '\n';
1145 if (!layout_modules_.empty()) {
1146 os << "\\begin_modules" << '\n';
1147 LayoutModuleList::const_iterator it = layout_modules_.begin();
1148 LayoutModuleList::const_iterator en = layout_modules_.end();
1149 for (; it != en; ++it)
1151 os << "\\end_modules" << '\n';
1155 if (!included_children_.empty()) {
1156 os << "\\begin_includeonly" << '\n';
1157 list<string>::const_iterator it = included_children_.begin();
1158 list<string>::const_iterator en = included_children_.end();
1159 for (; it != en; ++it)
1161 os << "\\end_includeonly" << '\n';
1163 os << "\\maintain_unincluded_children "
1164 << convert<string>(maintain_unincluded_children) << '\n';
1166 // local layout information
1167 docstring const local_layout = getLocalLayout(false);
1168 if (!local_layout.empty()) {
1169 // remove '\n' from the end
1170 docstring const tmplocal = rtrim(local_layout, "\n");
1171 os << "\\begin_local_layout\n"
1172 << to_utf8(tmplocal)
1173 << "\n\\end_local_layout\n";
1175 docstring const forced_local_layout = getLocalLayout(true);
1176 if (!forced_local_layout.empty()) {
1177 // remove '\n' from the end
1178 docstring const tmplocal = rtrim(forced_local_layout, "\n");
1179 os << "\\begin_forced_local_layout\n"
1180 << to_utf8(tmplocal)
1181 << "\n\\end_forced_local_layout\n";
1184 // then the text parameters
1185 if (language != ignore_language)
1186 os << "\\language " << language->lang() << '\n';
1187 os << "\\language_package " << lang_package
1188 << "\n\\inputencoding " << inputenc
1189 << "\n\\fontencoding " << fontenc
1190 << "\n\\font_roman \"" << fonts_roman[0]
1191 << "\" \"" << fonts_roman[1] << '"'
1192 << "\n\\font_sans \"" << fonts_sans[0]
1193 << "\" \"" << fonts_sans[1] << '"'
1194 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1195 << "\" \"" << fonts_typewriter[1] << '"'
1196 << "\n\\font_math \"" << fonts_math[0]
1197 << "\" \"" << fonts_math[1] << '"'
1198 << "\n\\font_default_family " << fonts_default_family
1199 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1200 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1201 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1202 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1203 << ' ' << fonts_sans_scale[1]
1204 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1205 << ' ' << fonts_typewriter_scale[1]
1207 if (!fonts_cjk.empty()) {
1208 os << "\\font_cjk " << fonts_cjk << '\n';
1210 os << "\\use_microtype " << convert<string>(use_microtype) << '\n';
1211 os << "\\use_dash_ligatures " << convert<string>(use_dash_ligatures) << '\n';
1212 os << "\\graphics " << graphics_driver << '\n';
1213 os << "\\default_output_format " << default_output_format << '\n';
1214 os << "\\output_sync " << output_sync << '\n';
1215 if (!output_sync_macro.empty())
1216 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1217 os << "\\bibtex_command " << bibtex_command << '\n';
1218 os << "\\index_command " << index_command << '\n';
1220 if (!float_placement.empty()) {
1221 os << "\\float_placement " << float_placement << '\n';
1223 os << "\\paperfontsize " << fontsize << '\n';
1225 spacing().writeFile(os);
1226 pdfoptions().writeFile(os);
1228 os << "\\papersize " << string_papersize[papersize]
1229 << "\n\\use_geometry " << convert<string>(use_geometry);
1230 map<string, string> const & packages = auto_packages();
1231 for (map<string, string>::const_iterator it = packages.begin();
1232 it != packages.end(); ++it)
1233 os << "\n\\use_package " << it->first << ' '
1234 << use_package(it->first);
1236 os << "\n\\cite_engine ";
1238 if (!cite_engine_.empty()) {
1239 LayoutModuleList::const_iterator be = cite_engine_.begin();
1240 LayoutModuleList::const_iterator en = cite_engine_.end();
1241 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1250 os << "\n\\cite_engine_type " << theCiteEnginesList.getTypeAsString(cite_engine_type_);
1252 if (!biblio_style.empty())
1253 os << "\n\\biblio_style " << biblio_style;
1254 if (!biblio_opts.empty())
1255 os << "\n\\biblio_options " << biblio_opts;
1256 if (!biblatex_bibstyle.empty())
1257 os << "\n\\biblatex_bibstyle " << biblatex_bibstyle;
1258 if (!biblatex_citestyle.empty())
1259 os << "\n\\biblatex_citestyle " << biblatex_citestyle;
1260 if (!multibib.empty())
1261 os << "\n\\multibib " << multibib;
1263 os << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1264 << "\n\\use_indices " << convert<string>(use_indices)
1265 << "\n\\paperorientation " << string_orientation[orientation]
1266 << "\n\\suppress_date " << convert<string>(suppress_date)
1267 << "\n\\justification " << convert<string>(justification)
1268 << "\n\\use_refstyle " << use_refstyle
1270 if (isbackgroundcolor == true)
1271 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1272 if (isfontcolor == true)
1273 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1274 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1275 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1276 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1277 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1279 BranchList::const_iterator it = branchlist().begin();
1280 BranchList::const_iterator end = branchlist().end();
1281 for (; it != end; ++it) {
1282 os << "\\branch " << to_utf8(it->branch())
1283 << "\n\\selected " << it->isSelected()
1284 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1285 << "\n\\color " << lyx::X11hexname(it->color())
1290 IndicesList::const_iterator iit = indiceslist().begin();
1291 IndicesList::const_iterator iend = indiceslist().end();
1292 for (; iit != iend; ++iit) {
1293 os << "\\index " << to_utf8(iit->index())
1294 << "\n\\shortcut " << to_utf8(iit->shortcut())
1295 << "\n\\color " << lyx::X11hexname(iit->color())
1300 if (!paperwidth.empty())
1301 os << "\\paperwidth "
1302 << VSpace(paperwidth).asLyXCommand() << '\n';
1303 if (!paperheight.empty())
1304 os << "\\paperheight "
1305 << VSpace(paperheight).asLyXCommand() << '\n';
1306 if (!leftmargin.empty())
1307 os << "\\leftmargin "
1308 << VSpace(leftmargin).asLyXCommand() << '\n';
1309 if (!topmargin.empty())
1310 os << "\\topmargin "
1311 << VSpace(topmargin).asLyXCommand() << '\n';
1312 if (!rightmargin.empty())
1313 os << "\\rightmargin "
1314 << VSpace(rightmargin).asLyXCommand() << '\n';
1315 if (!bottommargin.empty())
1316 os << "\\bottommargin "
1317 << VSpace(bottommargin).asLyXCommand() << '\n';
1318 if (!headheight.empty())
1319 os << "\\headheight "
1320 << VSpace(headheight).asLyXCommand() << '\n';
1321 if (!headsep.empty())
1323 << VSpace(headsep).asLyXCommand() << '\n';
1324 if (!footskip.empty())
1326 << VSpace(footskip).asLyXCommand() << '\n';
1327 if (!columnsep.empty())
1328 os << "\\columnsep "
1329 << VSpace(columnsep).asLyXCommand() << '\n';
1330 os << "\\secnumdepth " << secnumdepth
1331 << "\n\\tocdepth " << tocdepth
1332 << "\n\\paragraph_separation "
1333 << string_paragraph_separation[paragraph_separation];
1334 if (!paragraph_separation)
1335 os << "\n\\paragraph_indentation "
1336 << (pimpl_->parindent.empty() ? "default" : pimpl_->parindent.asString());
1338 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1339 os << "\n\\is_math_indent " << is_math_indent;
1340 if (is_math_indent && math_indentation != "default")
1341 os << "\n\\math_indentation " << math_indentation;
1342 os << "\n\\quotes_style "
1343 << string_quotes_style[quotes_style]
1344 << "\n\\dynamic_quotes " << dynamic_quotes
1345 << "\n\\papercolumns " << columns
1346 << "\n\\papersides " << sides
1347 << "\n\\paperpagestyle " << pagestyle << '\n';
1348 if (!listings_params.empty())
1349 os << "\\listings_params \"" <<
1350 InsetListingsParams(listings_params).encodedString() << "\"\n";
1351 for (int i = 0; i < 4; ++i) {
1352 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1353 if (user_defined_bullet(i).getFont() != -1) {
1354 os << "\\bullet " << i << " "
1355 << user_defined_bullet(i).getFont() << " "
1356 << user_defined_bullet(i).getCharacter() << " "
1357 << user_defined_bullet(i).getSize() << "\n";
1361 os << "\\bulletLaTeX " << i << " \""
1362 << lyx::to_ascii(user_defined_bullet(i).getText())
1368 os << "\\tracking_changes "
1369 << (save_transient_properties ? convert<string>(track_changes) : "false")
1372 os << "\\output_changes "
1373 << (save_transient_properties ? convert<string>(output_changes) : "false")
1376 os << "\\html_math_output " << html_math_output << '\n'
1377 << "\\html_css_as_file " << html_css_as_file << '\n'
1378 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1380 if (html_math_img_scale != 1.0)
1381 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1382 if (!html_latex_start.empty())
1383 os << "\\html_latex_start " << html_latex_start << '\n';
1384 if (!html_latex_end.empty())
1385 os << "\\html_latex_end " << html_latex_end << '\n';
1387 os << pimpl_->authorlist;
1391 void BufferParams::validate(LaTeXFeatures & features) const
1393 features.require(documentClass().requires());
1395 if (columns > 1 && language->rightToLeft())
1396 features.require("rtloutputdblcol");
1398 if (output_changes) {
1399 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1400 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1401 LaTeXFeatures::isAvailable("xcolor");
1403 switch (features.runparams().flavor) {
1404 case OutputParams::LATEX:
1405 case OutputParams::DVILUATEX:
1407 features.require("ct-dvipost");
1408 features.require("dvipost");
1409 } else if (xcolorulem) {
1410 features.require("ct-xcolor-ulem");
1411 features.require("ulem");
1412 features.require("xcolor");
1414 features.require("ct-none");
1417 case OutputParams::LUATEX:
1418 case OutputParams::PDFLATEX:
1419 case OutputParams::XETEX:
1421 features.require("ct-xcolor-ulem");
1422 features.require("ulem");
1423 features.require("xcolor");
1424 // improves color handling in PDF output
1425 features.require("pdfcolmk");
1427 features.require("ct-none");
1435 // Floats with 'Here definitely' as default setting.
1436 if (float_placement.find('H') != string::npos)
1437 features.require("float");
1439 for (PackageMap::const_iterator it = use_packages.begin();
1440 it != use_packages.end(); ++it) {
1441 if (it->first == "amsmath") {
1442 // AMS Style is at document level
1443 if (it->second == package_on ||
1444 features.isProvided("amsmath"))
1445 features.require(it->first);
1446 } else if (it->second == package_on)
1447 features.require(it->first);
1450 // Document-level line spacing
1451 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1452 features.require("setspace");
1454 // the bullet shapes are buffer level not paragraph level
1455 // so they are tested here
1456 for (int i = 0; i < 4; ++i) {
1457 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1459 int const font = user_defined_bullet(i).getFont();
1461 int const c = user_defined_bullet(i).getCharacter();
1467 features.require("latexsym");
1469 } else if (font == 1) {
1470 features.require("amssymb");
1471 } else if (font >= 2 && font <= 5) {
1472 features.require("pifont");
1476 if (pdfoptions().use_hyperref) {
1477 features.require("hyperref");
1478 // due to interferences with babel and hyperref, the color package has to
1479 // be loaded after hyperref when hyperref is used with the colorlinks
1480 // option, see http://www.lyx.org/trac/ticket/5291
1481 if (pdfoptions().colorlinks)
1482 features.require("color");
1484 if (!listings_params.empty()) {
1485 // do not test validity because listings_params is
1486 // supposed to be valid
1488 InsetListingsParams(listings_params).separatedParams(true);
1489 // we can't support all packages, but we should load the color package
1490 if (par.find("\\color", 0) != string::npos)
1491 features.require("color");
1494 // some languages are only available via polyglossia
1495 if (features.hasPolyglossiaExclusiveLanguages())
1496 features.require("polyglossia");
1498 if (useNonTeXFonts && fontsMath() != "auto")
1499 features.require("unicode-math");
1502 features.require("microtype");
1504 if (!language->requires().empty())
1505 features.require(language->requires());
1509 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1510 FileName const & filepath) const
1512 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1513 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1514 // \RequirePackage to do so, rather than the normal \usepackage
1515 // Do not try to load any other package before the document class, unless you
1516 // have a thorough understanding of the LATEX internals and know exactly what you
1518 if (features.mustProvide("fix-cm"))
1519 os << "\\RequirePackage{fix-cm}\n";
1520 // Likewise for fixltx2e. If other packages conflict with this policy,
1521 // treat it as a package bug (and report it!)
1522 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1523 if (features.mustProvide("fixltx2e"))
1524 os << "\\RequirePackage{fixltx2e}\n";
1526 os << "\\documentclass";
1528 DocumentClass const & tclass = documentClass();
1530 ostringstream clsoptions; // the document class options.
1532 if (tokenPos(tclass.opt_fontsize(),
1533 '|', fontsize) >= 0) {
1534 // only write if existing in list (and not default)
1535 clsoptions << fontsize << "pt,";
1538 // all paper sizes except of A4, A5, B5 and the US sizes need the
1540 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1541 && papersize != PAPER_USLETTER
1542 && papersize != PAPER_USLEGAL
1543 && papersize != PAPER_USEXECUTIVE
1544 && papersize != PAPER_A4
1545 && papersize != PAPER_A5
1546 && papersize != PAPER_B5;
1548 if (!use_geometry) {
1549 switch (papersize) {
1551 clsoptions << "a4paper,";
1553 case PAPER_USLETTER:
1554 clsoptions << "letterpaper,";
1557 clsoptions << "a5paper,";
1560 clsoptions << "b5paper,";
1562 case PAPER_USEXECUTIVE:
1563 clsoptions << "executivepaper,";
1566 clsoptions << "legalpaper,";
1600 if (sides != tclass.sides()) {
1603 clsoptions << "oneside,";
1606 clsoptions << "twoside,";
1612 if (columns != tclass.columns()) {
1614 clsoptions << "twocolumn,";
1616 clsoptions << "onecolumn,";
1620 && orientation == ORIENTATION_LANDSCAPE)
1621 clsoptions << "landscape,";
1624 clsoptions << "fleqn,";
1626 // language should be a parameter to \documentclass
1627 if (language->babel() == "hebrew"
1628 && default_language->babel() != "hebrew")
1629 // This seems necessary
1630 features.useLanguage(default_language);
1632 ostringstream language_options;
1633 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1634 bool const use_polyglossia = features.usePolyglossia();
1635 bool const global = lyxrc.language_global_options;
1636 if (use_babel || (use_polyglossia && global)) {
1637 language_options << features.getBabelLanguages();
1638 if (!language->babel().empty()) {
1639 if (!language_options.str().empty())
1640 language_options << ',';
1641 language_options << language->babel();
1643 if (global && !features.needBabelLangOptions()
1644 && !language_options.str().empty())
1645 clsoptions << language_options.str() << ',';
1648 // the predefined options from the layout
1649 if (use_default_options && !tclass.options().empty())
1650 clsoptions << tclass.options() << ',';
1652 // the user-defined options
1653 if (!options.empty()) {
1654 clsoptions << options << ',';
1657 string strOptions(clsoptions.str());
1658 if (!strOptions.empty()) {
1659 strOptions = rtrim(strOptions, ",");
1661 os << '[' << from_utf8(strOptions) << ']';
1664 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1665 // end of \documentclass defs
1667 // if we use fontspec or newtxmath, we have to load the AMS packages here
1668 string const ams = features.loadAMSPackages();
1669 bool const ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1");
1670 bool const use_newtxmath =
1671 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1672 ot1, false, false) == "newtxmath";
1673 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1674 os << from_ascii(ams);
1676 if (useNonTeXFonts) {
1677 if (!features.isProvided("fontspec"))
1678 os << "\\usepackage{fontspec}\n";
1679 if (features.mustProvide("unicode-math")
1680 && features.isAvailable("unicode-math"))
1681 os << "\\usepackage{unicode-math}\n";
1684 // font selection must be done before loading fontenc.sty
1685 string const fonts = loadFonts(features);
1687 os << from_utf8(fonts);
1689 if (fonts_default_family != "default")
1690 os << "\\renewcommand{\\familydefault}{\\"
1691 << from_ascii(fonts_default_family) << "}\n";
1693 // set font encoding
1694 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1695 if (!useNonTeXFonts && !features.isProvided("fontenc")
1696 && main_font_encoding() != "default") {
1697 // get main font encodings
1698 vector<string> fontencs = font_encodings();
1699 // get font encodings of secondary languages
1700 features.getFontEncodings(fontencs);
1701 if (!fontencs.empty()) {
1702 os << "\\usepackage["
1703 << from_ascii(getStringFromVector(fontencs))
1708 // handle inputenc etc.
1709 writeEncodingPreamble(os, features);
1712 if (!features.runparams().includeall && !included_children_.empty()) {
1713 os << "\\includeonly{";
1714 list<string>::const_iterator it = included_children_.begin();
1715 list<string>::const_iterator en = included_children_.end();
1717 for (; it != en; ++it) {
1718 string incfile = *it;
1719 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1720 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1722 if (!features.runparams().nice)
1724 // \includeonly doesn't want an extension
1725 incfile = changeExtension(incfile, string());
1726 incfile = support::latex_path(incfile);
1727 if (!incfile.empty()) {
1730 os << from_utf8(incfile);
1737 if (!features.isProvided("geometry")
1738 && (use_geometry || nonstandard_papersize)) {
1739 odocstringstream ods;
1740 if (!getGraphicsDriver("geometry").empty())
1741 ods << getGraphicsDriver("geometry");
1742 if (orientation == ORIENTATION_LANDSCAPE)
1743 ods << ",landscape";
1744 switch (papersize) {
1746 if (!paperwidth.empty())
1747 ods << ",paperwidth="
1748 << from_ascii(paperwidth);
1749 if (!paperheight.empty())
1750 ods << ",paperheight="
1751 << from_ascii(paperheight);
1753 case PAPER_USLETTER:
1754 ods << ",letterpaper";
1757 ods << ",legalpaper";
1759 case PAPER_USEXECUTIVE:
1760 ods << ",executivepaper";
1849 docstring const g_options = trim(ods.str(), ",");
1850 os << "\\usepackage";
1851 if (!g_options.empty())
1852 os << '[' << g_options << ']';
1853 os << "{geometry}\n";
1854 // output this only if use_geometry is true
1856 os << "\\geometry{verbose";
1857 if (!topmargin.empty())
1858 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1859 if (!bottommargin.empty())
1860 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1861 if (!leftmargin.empty())
1862 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1863 if (!rightmargin.empty())
1864 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1865 if (!headheight.empty())
1866 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1867 if (!headsep.empty())
1868 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1869 if (!footskip.empty())
1870 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1871 if (!columnsep.empty())
1872 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1875 } else if (orientation == ORIENTATION_LANDSCAPE
1876 || papersize != PAPER_DEFAULT) {
1877 features.require("papersize");
1880 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1881 if (pagestyle == "fancy")
1882 os << "\\usepackage{fancyhdr}\n";
1883 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1886 // only output when the background color is not default
1887 if (isbackgroundcolor == true) {
1888 // only require color here, the background color will be defined
1889 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1891 features.require("color");
1892 features.require("pagecolor");
1895 // only output when the font color is not default
1896 if (isfontcolor == true) {
1897 // only require color here, the font color will be defined
1898 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1900 features.require("color");
1901 features.require("fontcolor");
1904 // Only if class has a ToC hierarchy
1905 if (tclass.hasTocLevels()) {
1906 if (secnumdepth != tclass.secnumdepth()) {
1907 os << "\\setcounter{secnumdepth}{"
1911 if (tocdepth != tclass.tocdepth()) {
1912 os << "\\setcounter{tocdepth}{"
1918 if (paragraph_separation) {
1919 // when skip separation
1920 switch (getDefSkip().kind()) {
1921 case VSpace::SMALLSKIP:
1922 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1924 case VSpace::MEDSKIP:
1925 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1927 case VSpace::BIGSKIP:
1928 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1930 case VSpace::LENGTH:
1931 os << "\\setlength{\\parskip}{"
1932 << from_utf8(getDefSkip().length().asLatexString())
1935 default: // should never happen // Then delete it.
1936 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1939 os << "\\setlength{\\parindent}{0pt}\n";
1941 // when separation by indentation
1942 // only output something when a width is given
1943 if (!getParIndent().empty()) {
1944 os << "\\setlength{\\parindent}{"
1945 << from_utf8(getParIndent().asLatexString())
1950 if (is_math_indent) {
1951 // when formula indentation
1952 // only output something when it is not the default
1953 if (math_indentation != "default") {
1954 os << "\\setlength{\\mathindent}{"
1955 << from_utf8(math_indentation)
1960 // Now insert the LyX specific LaTeX commands...
1961 features.resolveAlternatives();
1962 features.expandMultiples();
1965 if (!output_sync_macro.empty())
1966 os << from_utf8(output_sync_macro) +"\n";
1967 else if (features.runparams().flavor == OutputParams::LATEX)
1968 os << "\\usepackage[active]{srcltx}\n";
1969 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1970 os << "\\synctex=-1\n";
1973 // The package options (via \PassOptionsToPackage)
1974 os << from_ascii(features.getPackageOptions());
1976 // due to interferences with babel and hyperref, the color package has to
1977 // be loaded (when it is not already loaded) before babel when hyperref
1978 // is used with the colorlinks option, see
1979 // http://www.lyx.org/trac/ticket/5291
1980 // we decided therefore to load color always before babel, see
1981 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1982 os << from_ascii(features.getColorOptions());
1984 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1985 // we have to call babel before
1987 && (features.isRequired("jurabib")
1988 || features.isRequired("hyperref")
1989 || features.isRequired("varioref")
1990 || features.isRequired("vietnamese")
1991 || features.isRequired("japanese"))) {
1992 os << features.getBabelPresettings();
1994 os << from_utf8(babelCall(language_options.str(),
1995 features.needBabelLangOptions())) + '\n';
1996 os << features.getBabelPostsettings();
1999 // The optional packages;
2000 os << from_ascii(features.getPackages());
2002 // Additional Indices
2003 if (features.isRequired("splitidx")) {
2004 IndicesList::const_iterator iit = indiceslist().begin();
2005 IndicesList::const_iterator iend = indiceslist().end();
2006 for (; iit != iend; ++iit) {
2007 os << "\\newindex{";
2008 os << escape(iit->shortcut());
2014 os << from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
2017 // * Hyperref manual: "Make sure it comes last of your loaded
2018 // packages, to give it a fighting chance of not being over-written,
2019 // since its job is to redefine many LaTeX commands."
2020 // * Email from Heiko Oberdiek: "It is usually better to load babel
2021 // before hyperref. Then hyperref has a chance to detect babel.
2022 // * Has to be loaded before the "LyX specific LaTeX commands" to
2023 // avoid errors with algorithm floats.
2024 // use hyperref explicitly if it is required
2025 if (features.isRequired("hyperref")) {
2026 OutputParams tmp_params = features.runparams();
2027 pdfoptions().writeLaTeX(tmp_params, os,
2028 features.isProvided("hyperref"));
2029 // correctly break URLs with hyperref and dvi output
2030 if (features.runparams().flavor == OutputParams::LATEX
2031 && features.isAvailable("breakurl"))
2032 os << "\\usepackage{breakurl}\n";
2033 } else if (features.isRequired("nameref"))
2034 // hyperref loads this automatically
2035 os << "\\usepackage{nameref}\n";
2037 // bibtopic needs to be loaded after hyperref.
2038 // the dot provides the aux file naming which LyX can detect.
2039 if (features.mustProvide("bibtopic"))
2040 os << "\\usepackage[dot]{bibtopic}\n";
2042 // Will be surrounded by \makeatletter and \makeatother when not empty
2043 otexstringstream atlyxpreamble;
2045 // Some macros LyX will need
2047 TexString tmppreamble = features.getMacros();
2048 if (!tmppreamble.str.empty())
2049 atlyxpreamble << "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2050 "LyX specific LaTeX commands.\n"
2051 << move(tmppreamble)
2054 // the text class specific preamble
2056 docstring tmppreamble = features.getTClassPreamble();
2057 if (!tmppreamble.empty())
2058 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2059 "Textclass specific LaTeX commands.\n"
2063 // suppress date if selected
2064 // use \@ifundefined because we cannot be sure that every document class
2065 // has a \date command
2067 atlyxpreamble << "\\@ifundefined{date}{}{\\date{}}\n";
2069 /* the user-defined preamble */
2070 if (!containsOnly(preamble, " \n\t")) {
2072 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2073 "User specified LaTeX commands.\n";
2075 // Check if the user preamble contains uncodable glyphs
2076 odocstringstream user_preamble;
2077 docstring uncodable_glyphs;
2078 Encoding const * const enc = features.runparams().encoding;
2080 for (size_t n = 0; n < preamble.size(); ++n) {
2081 char_type c = preamble[n];
2082 if (!enc->encodable(c)) {
2083 docstring const glyph(1, c);
2084 LYXERR0("Uncodable character '"
2086 << "' in user preamble!");
2087 uncodable_glyphs += glyph;
2088 if (features.runparams().dryrun) {
2089 user_preamble << "<" << _("LyX Warning: ")
2090 << _("uncodable character") << " '";
2091 user_preamble.put(c);
2092 user_preamble << "'>";
2095 user_preamble.put(c);
2098 user_preamble << preamble;
2100 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2101 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2102 frontend::Alert::warning(
2103 _("Uncodable character in user preamble"),
2105 _("The user preamble of your document contains glyphs "
2106 "that are unknown in the current document encoding "
2107 "(namely %1$s).\nThese glyphs are omitted "
2108 " from the output, which may result in "
2109 "incomplete output."
2110 "\n\nPlease select an appropriate "
2111 "document encoding\n"
2112 "(such as utf8) or change the "
2113 "preamble code accordingly."),
2116 atlyxpreamble << user_preamble.str() << '\n';
2119 // footmisc must be loaded after setspace
2120 // Load it here to avoid clashes with footmisc loaded in the user
2121 // preamble. For that reason we also pass the options via
2122 // \PassOptionsToPackage in getPreamble() and not here.
2123 if (features.mustProvide("footmisc"))
2124 atlyxpreamble << "\\usepackage{footmisc}\n";
2126 // subfig loads internally the LaTeX package "caption". As
2127 // caption is a very popular package, users will load it in
2128 // the preamble. Therefore we must load subfig behind the
2129 // user-defined preamble and check if the caption package was
2130 // loaded or not. For the case that caption is loaded before
2131 // subfig, there is the subfig option "caption=false". This
2132 // option also works when a koma-script class is used and
2133 // koma's own caption commands are used instead of caption. We
2134 // use \PassOptionsToPackage here because the user could have
2135 // already loaded subfig in the preamble.
2136 if (features.mustProvide("subfig"))
2137 atlyxpreamble << "\\@ifundefined{showcaptionsetup}{}{%\n"
2138 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2139 "\\usepackage{subfig}\n";
2141 // Itemize bullet settings need to be last in case the user
2142 // defines their own bullets that use a package included
2143 // in the user-defined preamble -- ARRae
2144 // Actually it has to be done much later than that
2145 // since some packages like frenchb make modifications
2146 // at \begin{document} time -- JMarc
2147 docstring bullets_def;
2148 for (int i = 0; i < 4; ++i) {
2149 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2150 if (bullets_def.empty())
2151 bullets_def += "\\AtBeginDocument{\n";
2152 bullets_def += " \\def\\labelitemi";
2154 // `i' is one less than the item to modify
2161 bullets_def += "ii";
2167 bullets_def += '{' +
2168 user_defined_bullet(i).getText()
2173 if (!bullets_def.empty())
2174 atlyxpreamble << bullets_def << "}\n\n";
2176 if (!atlyxpreamble.empty())
2177 os << "\n\\makeatletter\n"
2178 << atlyxpreamble.release()
2179 << "\\makeatother\n\n";
2181 // We try to load babel late, in case it interferes with other packages.
2182 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2183 // called after babel, though.
2184 if (use_babel && !features.isRequired("jurabib")
2185 && !features.isRequired("hyperref")
2186 && !features.isRequired("varioref")
2187 && !features.isRequired("vietnamese")
2188 && !features.isRequired("japanese")) {
2189 os << features.getBabelPresettings();
2191 os << from_utf8(babelCall(language_options.str(),
2192 features.needBabelLangOptions())) + '\n';
2193 os << features.getBabelPostsettings();
2195 if (features.isRequired("bicaption"))
2196 os << "\\usepackage{bicaption}\n";
2197 if (!listings_params.empty() || features.mustProvide("listings"))
2198 os << "\\usepackage{listings}\n";
2199 if (!listings_params.empty()) {
2201 // do not test validity because listings_params is
2202 // supposed to be valid
2204 InsetListingsParams(listings_params).separatedParams(true);
2205 os << from_utf8(par);
2209 // xunicode only needs to be loaded if tipa is used
2210 // (the rest is obsoleted by the new TU encoding).
2211 // It needs to be loaded at least after amsmath, amssymb,
2212 // esint and the other packages that provide special glyphs
2213 if (features.mustProvide("tipa") && useNonTeXFonts) {
2214 // The package officially only supports XeTeX, but also works
2215 // with LuaTeX. Thus we work around its XeTeX test.
2216 if (features.runparams().flavor != OutputParams::XETEX) {
2217 os << "% Pretend to xunicode that we are XeTeX\n"
2218 << "\\def\\XeTeXpicfile{}\n";
2220 os << "\\usepackage{xunicode}\n";
2223 // Polyglossia must be loaded last ...
2224 if (use_polyglossia) {
2226 os << "\\usepackage{polyglossia}\n";
2227 // set the main language
2228 os << "\\setdefaultlanguage";
2229 if (!language->polyglossiaOpts().empty())
2230 os << "[" << from_ascii(language->polyglossiaOpts()) << "]";
2231 os << "{" << from_ascii(language->polyglossia()) << "}\n";
2232 // now setup the other languages
2233 set<string> const polylangs =
2234 features.getPolyglossiaLanguages();
2235 for (set<string>::const_iterator mit = polylangs.begin();
2236 mit != polylangs.end() ; ++mit) {
2237 // We do not output the options here; they are output in
2238 // the language switch commands. This is safer if multiple
2239 // varieties are used.
2240 if (*mit == language->polyglossia())
2242 os << "\\setotherlanguage";
2243 os << "{" << from_ascii(*mit) << "}\n";
2247 // ... but before biblatex (see #7065)
2248 if (features.mustProvide("biblatex")) {
2251 os << "\\usepackage";
2252 if (!biblatex_bibstyle.empty()
2253 && (biblatex_bibstyle == biblatex_citestyle)) {
2254 opts = "style=" + biblatex_bibstyle;
2257 if (!biblatex_bibstyle.empty()) {
2258 opts = "bibstyle=" + biblatex_bibstyle;
2261 if (!biblatex_citestyle.empty()) {
2262 opts += delim + "citestyle=" + biblatex_citestyle;
2266 if (!multibib.empty() && multibib != "child") {
2267 opts += delim + "refsection=" + multibib;
2270 if (bibtexCommand() == "bibtex8"
2271 || prefixIs(bibtexCommand(), "bibtex8 ")) {
2272 opts += delim + "backend=bibtex8";
2274 } else if (bibtexCommand() == "bibtex"
2275 || prefixIs(bibtexCommand(), "bibtex ")) {
2276 opts += delim + "backend=bibtex";
2279 if (!biblio_opts.empty())
2280 opts += delim + biblio_opts;
2282 os << "[" << opts << "]";
2283 os << "{biblatex}\n";
2287 // Load custom language package here
2288 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2289 if (lang_package == "default")
2290 os << from_utf8(lyxrc.language_custom_package);
2292 os << from_utf8(lang_package);
2296 docstring const i18npreamble =
2297 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2298 if (!i18npreamble.empty())
2299 os << i18npreamble + '\n';
2305 void BufferParams::useClassDefaults()
2307 DocumentClass const & tclass = documentClass();
2309 sides = tclass.sides();
2310 columns = tclass.columns();
2311 pagestyle = tclass.pagestyle();
2312 use_default_options = true;
2313 // Only if class has a ToC hierarchy
2314 if (tclass.hasTocLevels()) {
2315 secnumdepth = tclass.secnumdepth();
2316 tocdepth = tclass.tocdepth();
2321 bool BufferParams::hasClassDefaults() const
2323 DocumentClass const & tclass = documentClass();
2325 return sides == tclass.sides()
2326 && columns == tclass.columns()
2327 && pagestyle == tclass.pagestyle()
2328 && use_default_options
2329 && secnumdepth == tclass.secnumdepth()
2330 && tocdepth == tclass.tocdepth();
2334 DocumentClass const & BufferParams::documentClass() const
2340 DocumentClassConstPtr BufferParams::documentClassPtr() const
2346 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2348 // evil, but this function is evil
2349 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2350 invalidateConverterCache();
2354 bool BufferParams::setBaseClass(string const & classname)
2356 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2357 LayoutFileList & bcl = LayoutFileList::get();
2358 if (!bcl.haveClass(classname)) {
2360 bformat(_("The layout file:\n"
2362 "could not be found. A default textclass with default\n"
2363 "layouts will be used. LyX will not be able to produce\n"
2365 from_utf8(classname));
2366 frontend::Alert::error(_("Document class not found"), s);
2367 bcl.addEmptyClass(classname);
2370 bool const success = bcl[classname].load();
2373 bformat(_("Due to some error in it, the layout file:\n"
2375 "could not be loaded. A default textclass with default\n"
2376 "layouts will be used. LyX will not be able to produce\n"
2378 from_utf8(classname));
2379 frontend::Alert::error(_("Could not load class"), s);
2380 bcl.addEmptyClass(classname);
2383 pimpl_->baseClass_ = classname;
2384 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2389 LayoutFile const * BufferParams::baseClass() const
2391 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2392 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2398 LayoutFileIndex const & BufferParams::baseClassID() const
2400 return pimpl_->baseClass_;
2404 void BufferParams::makeDocumentClass(bool const clone)
2409 invalidateConverterCache();
2410 LayoutModuleList mods;
2411 LayoutModuleList ces;
2412 LayoutModuleList::iterator it = layout_modules_.begin();
2413 LayoutModuleList::iterator en = layout_modules_.end();
2414 for (; it != en; ++it)
2415 mods.push_back(*it);
2417 it = cite_engine_.begin();
2418 en = cite_engine_.end();
2419 for (; it != en; ++it)
2422 doc_class_ = getDocumentClass(*baseClass(), mods, ces, clone);
2424 TextClass::ReturnValues success = TextClass::OK;
2425 if (!forced_local_layout_.empty())
2426 success = doc_class_->read(to_utf8(forced_local_layout_),
2428 if (!local_layout_.empty() &&
2429 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2430 success = doc_class_->read(to_utf8(local_layout_), TextClass::MODULE);
2431 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2432 docstring const msg = _("Error reading internal layout information");
2433 frontend::Alert::warning(_("Read Error"), msg);
2438 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2440 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2444 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2446 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2450 docstring BufferParams::getLocalLayout(bool forced) const
2453 return from_utf8(doc_class_->forcedLayouts());
2455 return local_layout_;
2459 void BufferParams::setLocalLayout(docstring const & layout, bool forced)
2462 forced_local_layout_ = layout;
2464 local_layout_ = layout;
2468 bool BufferParams::addLayoutModule(string const & modName)
2470 LayoutModuleList::const_iterator it = layout_modules_.begin();
2471 LayoutModuleList::const_iterator end = layout_modules_.end();
2472 for (; it != end; ++it)
2475 layout_modules_.push_back(modName);
2480 string BufferParams::bufferFormat() const
2482 return documentClass().outputFormat();
2486 bool BufferParams::isExportable(string const & format, bool need_viewable) const
2488 FormatList const & formats = exportableFormats(need_viewable);
2489 FormatList::const_iterator fit = formats.begin();
2490 FormatList::const_iterator end = formats.end();
2491 for (; fit != end ; ++fit) {
2492 if ((*fit)->name() == format)
2499 FormatList const & BufferParams::exportableFormats(bool only_viewable) const
2501 FormatList & cached = only_viewable ?
2502 pimpl_->viewableFormatList : pimpl_->exportableFormatList;
2503 bool & valid = only_viewable ?
2504 pimpl_->isViewCacheValid : pimpl_->isExportCacheValid;
2508 vector<string> const backs = backends();
2509 set<string> excludes;
2510 if (useNonTeXFonts) {
2511 excludes.insert("latex");
2512 excludes.insert("pdflatex");
2515 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2516 for (vector<string>::const_iterator it = backs.begin() + 1;
2517 it != backs.end(); ++it) {
2518 FormatList r = theConverters().getReachable(*it, only_viewable,
2520 result.insert(result.end(), r.begin(), r.end());
2522 sort(result.begin(), result.end(), Format::formatSorter);
2529 vector<string> BufferParams::backends() const
2532 string const buffmt = bufferFormat();
2534 // FIXME: Don't hardcode format names here, but use a flag
2535 if (buffmt == "latex") {
2536 if (encoding().package() == Encoding::japanese)
2537 v.push_back("platex");
2539 if (!useNonTeXFonts) {
2540 v.push_back("pdflatex");
2541 v.push_back("latex");
2543 v.push_back("xetex");
2544 v.push_back("luatex");
2545 v.push_back("dviluatex");
2548 v.push_back(buffmt);
2550 v.push_back("xhtml");
2551 v.push_back("text");
2557 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2559 string const dformat = (format.empty() || format == "default") ?
2560 getDefaultOutputFormat() : format;
2561 DefaultFlavorCache::const_iterator it =
2562 default_flavors_.find(dformat);
2564 if (it != default_flavors_.end())
2567 OutputParams::FLAVOR result = OutputParams::LATEX;
2569 // FIXME It'd be better not to hardcode this, but to do
2570 // something with formats.
2571 if (dformat == "xhtml")
2572 result = OutputParams::HTML;
2573 else if (dformat == "text")
2574 result = OutputParams::TEXT;
2575 else if (dformat == "lyx")
2576 result = OutputParams::LYX;
2577 else if (dformat == "pdflatex")
2578 result = OutputParams::PDFLATEX;
2579 else if (dformat == "xetex")
2580 result = OutputParams::XETEX;
2581 else if (dformat == "luatex")
2582 result = OutputParams::LUATEX;
2583 else if (dformat == "dviluatex")
2584 result = OutputParams::DVILUATEX;
2586 // Try to determine flavor of default output format
2587 vector<string> backs = backends();
2588 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2589 // Get shortest path to format
2590 Graph::EdgePath path;
2591 for (vector<string>::const_iterator it = backs.begin();
2592 it != backs.end(); ++it) {
2593 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2594 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2599 result = theConverters().getFlavor(path);
2602 // cache this flavor
2603 default_flavors_[dformat] = result;
2608 string BufferParams::getDefaultOutputFormat() const
2610 if (!default_output_format.empty()
2611 && default_output_format != "default")
2612 return default_output_format;
2614 || encoding().package() == Encoding::japanese) {
2615 FormatList const & formats = exportableFormats(true);
2616 if (formats.empty())
2618 // return the first we find
2619 return formats.front()->name();
2622 return lyxrc.default_otf_view_format;
2623 return lyxrc.default_view_format;
2626 Font const BufferParams::getFont() const
2628 FontInfo f = documentClass().defaultfont();
2629 if (fonts_default_family == "rmdefault")
2630 f.setFamily(ROMAN_FAMILY);
2631 else if (fonts_default_family == "sfdefault")
2632 f.setFamily(SANS_FAMILY);
2633 else if (fonts_default_family == "ttdefault")
2634 f.setFamily(TYPEWRITER_FAMILY);
2635 return Font(f, language);
2639 InsetQuotesParams::QuoteStyle BufferParams::getQuoteStyle(string const & qs) const
2641 return quotesstyletranslator().find(qs);
2645 bool BufferParams::isLatex() const
2647 return documentClass().outputType() == LATEX;
2651 bool BufferParams::isLiterate() const
2653 return documentClass().outputType() == LITERATE;
2657 bool BufferParams::isDocBook() const
2659 return documentClass().outputType() == DOCBOOK;
2663 void BufferParams::readPreamble(Lexer & lex)
2665 if (lex.getString() != "\\begin_preamble")
2666 lyxerr << "Error (BufferParams::readPreamble):"
2667 "consistency check failed." << endl;
2669 preamble = lex.getLongString(from_ascii("\\end_preamble"));
2673 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2675 string const expected = forced ? "\\begin_forced_local_layout" :
2676 "\\begin_local_layout";
2677 if (lex.getString() != expected)
2678 lyxerr << "Error (BufferParams::readLocalLayout):"
2679 "consistency check failed." << endl;
2682 forced_local_layout_ =
2683 lex.getLongString(from_ascii("\\end_forced_local_layout"));
2685 local_layout_ = lex.getLongString(from_ascii("\\end_local_layout"));
2689 bool BufferParams::setLanguage(string const & lang)
2691 Language const *new_language = languages.getLanguage(lang);
2692 if (!new_language) {
2693 // Language lang was not found
2696 language = new_language;
2701 void BufferParams::readLanguage(Lexer & lex)
2703 if (!lex.next()) return;
2705 string const tmptok = lex.getString();
2707 // check if tmptok is part of tex_babel in tex-defs.h
2708 if (!setLanguage(tmptok)) {
2709 // Language tmptok was not found
2710 language = default_language;
2711 lyxerr << "Warning: Setting language `"
2712 << tmptok << "' to `" << language->lang()
2718 void BufferParams::readGraphicsDriver(Lexer & lex)
2723 string const tmptok = lex.getString();
2724 // check if tmptok is part of tex_graphics in tex_defs.h
2727 string const test = tex_graphics[n++];
2729 if (test == tmptok) {
2730 graphics_driver = tmptok;
2735 "Warning: graphics driver `$$Token' not recognized!\n"
2736 " Setting graphics driver to `default'.\n");
2737 graphics_driver = "default";
2744 void BufferParams::readBullets(Lexer & lex)
2749 int const index = lex.getInteger();
2751 int temp_int = lex.getInteger();
2752 user_defined_bullet(index).setFont(temp_int);
2753 temp_bullet(index).setFont(temp_int);
2755 user_defined_bullet(index).setCharacter(temp_int);
2756 temp_bullet(index).setCharacter(temp_int);
2758 user_defined_bullet(index).setSize(temp_int);
2759 temp_bullet(index).setSize(temp_int);
2763 void BufferParams::readBulletsLaTeX(Lexer & lex)
2765 // The bullet class should be able to read this.
2768 int const index = lex.getInteger();
2770 docstring const temp_str = lex.getDocString();
2772 user_defined_bullet(index).setText(temp_str);
2773 temp_bullet(index).setText(temp_str);
2777 void BufferParams::readModules(Lexer & lex)
2779 if (!lex.eatLine()) {
2780 lyxerr << "Error (BufferParams::readModules):"
2781 "Unexpected end of input." << endl;
2785 string mod = lex.getString();
2786 if (mod == "\\end_modules")
2788 addLayoutModule(mod);
2794 void BufferParams::readRemovedModules(Lexer & lex)
2796 if (!lex.eatLine()) {
2797 lyxerr << "Error (BufferParams::readRemovedModules):"
2798 "Unexpected end of input." << endl;
2802 string mod = lex.getString();
2803 if (mod == "\\end_removed_modules")
2805 removed_modules_.push_back(mod);
2808 // now we want to remove any removed modules that were previously
2809 // added. normally, that will be because default modules were added in
2810 // setBaseClass(), which gets called when \textclass is read at the
2811 // start of the read.
2812 list<string>::const_iterator rit = removed_modules_.begin();
2813 list<string>::const_iterator const ren = removed_modules_.end();
2814 for (; rit != ren; ++rit) {
2815 LayoutModuleList::iterator const mit = layout_modules_.begin();
2816 LayoutModuleList::iterator const men = layout_modules_.end();
2817 LayoutModuleList::iterator found = find(mit, men, *rit);
2820 layout_modules_.erase(found);
2825 void BufferParams::readIncludeonly(Lexer & lex)
2827 if (!lex.eatLine()) {
2828 lyxerr << "Error (BufferParams::readIncludeonly):"
2829 "Unexpected end of input." << endl;
2833 string child = lex.getString();
2834 if (child == "\\end_includeonly")
2836 included_children_.push_back(child);
2842 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2844 switch (papersize) {
2846 // could be anything, so don't guess
2848 case PAPER_CUSTOM: {
2849 if (purpose == XDVI && !paperwidth.empty() &&
2850 !paperheight.empty()) {
2851 // heightxwidth<unit>
2852 string first = paperwidth;
2853 string second = paperheight;
2854 if (orientation == ORIENTATION_LANDSCAPE)
2857 return first.erase(first.length() - 2)
2863 // dvips and dvipdfm do not know this
2864 if (purpose == DVIPS || purpose == DVIPDFM)
2868 if (purpose == DVIPS || purpose == DVIPDFM)
2872 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 // dvipdfm does not know this
2903 if (purpose == DVIPDFM)
2907 if (purpose == DVIPDFM)
2911 if (purpose == DVIPS || purpose == DVIPDFM)
2915 if (purpose == DVIPS || purpose == DVIPDFM)
2919 if (purpose == DVIPS || purpose == DVIPDFM)
2923 if (purpose == DVIPS || purpose == DVIPDFM)
2927 if (purpose == DVIPS || purpose == DVIPDFM)
2931 if (purpose == DVIPS || purpose == DVIPDFM)
2935 if (purpose == DVIPS || purpose == DVIPDFM)
2939 if (purpose == DVIPS || purpose == DVIPDFM)
2943 if (purpose == DVIPS || purpose == DVIPDFM)
2947 if (purpose == DVIPS || purpose == DVIPDFM)
2951 if (purpose == DVIPS || purpose == DVIPDFM)
2955 if (purpose == DVIPS || purpose == DVIPDFM)
2959 if (purpose == DVIPS || purpose == DVIPDFM)
2963 if (purpose == DVIPS || purpose == DVIPDFM)
2967 if (purpose == DVIPS || purpose == DVIPDFM)
2970 case PAPER_USEXECUTIVE:
2971 // dvipdfm does not know this
2972 if (purpose == DVIPDFM)
2977 case PAPER_USLETTER:
2979 if (purpose == XDVI)
2986 string const BufferParams::dvips_options() const
2990 // If the class loads the geometry package, we do not know which
2991 // paper size is used, since we do not set it (bug 7013).
2992 // Therefore we must not specify any argument here.
2993 // dvips gets the correct paper size via DVI specials in this case
2994 // (if the class uses the geometry package correctly).
2995 if (documentClass().provides("geometry"))
2999 && papersize == PAPER_CUSTOM
3000 && !lyxrc.print_paper_dimension_flag.empty()
3001 && !paperwidth.empty()
3002 && !paperheight.empty()) {
3003 // using a custom papersize
3004 result = lyxrc.print_paper_dimension_flag;
3005 result += ' ' + paperwidth;
3006 result += ',' + paperheight;
3008 string const paper_option = paperSizeName(DVIPS);
3009 if (!paper_option.empty() && (paper_option != "letter" ||
3010 orientation != ORIENTATION_LANDSCAPE)) {
3011 // dvips won't accept -t letter -t landscape.
3012 // In all other cases, include the paper size
3014 result = lyxrc.print_paper_flag;
3015 result += ' ' + paper_option;
3018 if (orientation == ORIENTATION_LANDSCAPE &&
3019 papersize != PAPER_CUSTOM)
3020 result += ' ' + lyxrc.print_landscape_flag;
3025 string const BufferParams::main_font_encoding() const
3027 return font_encodings().empty() ? "default" : font_encodings().back();
3031 vector<string> const BufferParams::font_encodings() const
3033 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
3035 vector<string> fontencs;
3037 // "default" means "no explicit font encoding"
3038 if (doc_fontenc != "default") {
3039 fontencs = getVectorFromString(doc_fontenc);
3040 if (!language->fontenc().empty()
3041 && ascii_lowercase(language->fontenc()) != "none") {
3042 vector<string> fencs = getVectorFromString(language->fontenc());
3043 vector<string>::const_iterator fit = fencs.begin();
3044 for (; fit != fencs.end(); ++fit) {
3045 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
3046 fontencs.push_back(*fit);
3055 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
3057 // suppress the babel call if there is no BabelName defined
3058 // for the document language in the lib/languages file and if no
3059 // other languages are used (lang_opts is then empty)
3060 if (lang_opts.empty())
3062 // either a specific language (AsBabelOptions setting in
3063 // lib/languages) or the prefs require the languages to
3064 // be submitted to babel itself (not the class).
3066 return "\\usepackage[" + lang_opts + "]{babel}";
3067 return "\\usepackage{babel}";
3071 docstring BufferParams::getGraphicsDriver(string const & package) const
3075 if (package == "geometry") {
3076 if (graphics_driver == "dvips"
3077 || graphics_driver == "dvipdfm"
3078 || graphics_driver == "pdftex"
3079 || graphics_driver == "vtex")
3080 result = from_ascii(graphics_driver);
3081 else if (graphics_driver == "dvipdfmx")
3082 result = from_ascii("dvipdfm");
3089 void BufferParams::writeEncodingPreamble(otexstream & os,
3090 LaTeXFeatures & features) const
3092 // XeTeX/LuaTeX: (see also #9740)
3093 // With Unicode fonts we use utf8-plain without encoding package.
3094 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
3095 // XeTeX must use ASCII encoding (see Buffer.cpp),
3096 // for LuaTeX, we load "luainputenc" (see below).
3097 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
3100 if (inputenc == "auto") {
3101 string const doc_encoding =
3102 language->encoding()->latexName();
3103 Encoding::Package const package =
3104 language->encoding()->package();
3106 // Create list of inputenc options:
3107 set<string> encodings;
3108 // luainputenc fails with more than one encoding
3109 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
3110 // list all input encodings used in the document
3111 encodings = features.getEncodingSet(doc_encoding);
3113 // If the "japanese" package (i.e. pLaTeX) is used,
3114 // inputenc must be omitted.
3115 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
3116 if ((!encodings.empty() || package == Encoding::inputenc)
3117 && !features.isRequired("japanese")
3118 && !features.isProvided("inputenc")) {
3119 os << "\\usepackage[";
3120 set<string>::const_iterator it = encodings.begin();
3121 set<string>::const_iterator const end = encodings.end();
3123 os << from_ascii(*it);
3126 for (; it != end; ++it)
3127 os << ',' << from_ascii(*it);
3128 if (package == Encoding::inputenc) {
3129 if (!encodings.empty())
3131 os << from_ascii(doc_encoding);
3133 if (features.runparams().flavor == OutputParams::LUATEX
3134 || features.runparams().flavor == OutputParams::DVILUATEX)
3135 os << "]{luainputenc}\n";
3137 os << "]{inputenc}\n";
3139 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3140 if (language->encoding()->name() == "utf8-cjk"
3141 && LaTeXFeatures::isAvailable("CJKutf8"))
3142 os << "\\usepackage{CJKutf8}\n";
3144 os << "\\usepackage{CJK}\n";
3146 } else if (inputenc != "default") {
3147 switch (encoding().package()) {
3148 case Encoding::none:
3149 case Encoding::japanese:
3151 case Encoding::inputenc:
3152 // do not load inputenc if japanese is used
3153 // or if the class provides inputenc
3154 if (features.isRequired("japanese")
3155 || features.isProvided("inputenc"))
3157 os << "\\usepackage[" << from_ascii(encoding().latexName());
3158 if (features.runparams().flavor == OutputParams::LUATEX
3159 || features.runparams().flavor == OutputParams::DVILUATEX)
3160 os << "]{luainputenc}\n";
3162 os << "]{inputenc}\n";
3165 if (encoding().name() == "utf8-cjk"
3166 && LaTeXFeatures::isAvailable("CJKutf8"))
3167 os << "\\usepackage{CJKutf8}\n";
3169 os << "\\usepackage{CJK}\n";
3172 // Load the CJK package if needed by a secondary language.
3173 // If the main encoding is some variant of UTF8, use CJKutf8.
3174 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3175 if (encoding().iconvName() == "UTF-8"
3176 && LaTeXFeatures::isAvailable("CJKutf8"))
3177 os << "\\usepackage{CJKutf8}\n";
3179 os << "\\usepackage{CJK}\n";
3185 string const BufferParams::parseFontName(string const & name) const
3187 string mangled = name;
3188 size_t const idx = mangled.find('[');
3189 if (idx == string::npos || idx == 0)
3192 return mangled.substr(0, idx - 1);
3196 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3198 if (fontsRoman() == "default" && fontsSans() == "default"
3199 && fontsTypewriter() == "default"
3200 && (fontsMath() == "default" || fontsMath() == "auto"))
3206 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3207 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3208 * Mapping=tex-text option assures TeX ligatures (such as "--")
3209 * are resolved. Note that tt does not use these ligatures.
3211 * -- add more GUI options?
3212 * -- add more fonts (fonts for other scripts)
3213 * -- if there's a way to find out if a font really supports
3214 * OldStyle, enable/disable the widget accordingly.
3216 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3217 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3218 // However, until v.2 (2010/07/11) fontspec only knew
3219 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3220 // was introduced for both XeTeX and LuaTeX (LuaTeX
3221 // didn't understand "Mapping=tex-text", while XeTeX
3222 // understood both. With most recent versions, both
3223 // variants are understood by both engines. However,
3224 // we want to provide support for at least TeXLive 2009
3225 // (for XeTeX; LuaTeX is only supported as of v.2)
3226 string const texmapping =
3227 (features.runparams().flavor == OutputParams::XETEX) ?
3228 "Mapping=tex-text" : "Ligatures=TeX";
3229 if (fontsRoman() != "default") {
3230 os << "\\setmainfont[" << texmapping;
3231 if (fonts_old_figures)
3232 os << ",Numbers=OldStyle";
3233 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3235 if (fontsSans() != "default") {
3236 string const sans = parseFontName(fontsSans());
3237 if (fontsSansScale() != 100)
3238 os << "\\setsansfont[Scale="
3239 << float(fontsSansScale()) / 100
3240 << "," << texmapping << "]{"
3243 os << "\\setsansfont[" << texmapping << "]{"
3246 if (fontsTypewriter() != "default") {
3247 string const mono = parseFontName(fontsTypewriter());
3248 if (fontsTypewriterScale() != 100)
3249 os << "\\setmonofont[Scale="
3250 << float(fontsTypewriterScale()) / 100
3254 os << "\\setmonofont{"
3261 bool const ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1");
3262 bool const dryrun = features.runparams().dryrun;
3263 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3264 bool const nomath = (fontsMath() == "default");
3267 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3268 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3272 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3273 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3274 nomath, fontsSansScale());
3276 // MONOSPACED/TYPEWRITER
3277 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3278 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3279 nomath, fontsTypewriterScale());
3282 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3283 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3290 Encoding const & BufferParams::encoding() const
3292 // Main encoding for LaTeX output.
3294 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3295 // As the "flavor" is only known once export started, this
3296 // cannot be handled here. Instead, runparams.encoding is set
3297 // to ASCII in Buffer::makeLaTeXFile (for export)
3298 // and Buffer::writeLaTeXSource (for preview).
3300 return *(encodings.fromLyXName("utf8-plain"));
3301 if (inputenc == "auto" || inputenc == "default")
3302 return *language->encoding();
3303 Encoding const * const enc = encodings.fromLyXName(inputenc);
3306 LYXERR0("Unknown inputenc value `" << inputenc
3307 << "'. Using `auto' instead.");
3308 return *language->encoding();
3312 bool BufferParams::addCiteEngine(string const & engine)
3314 LayoutModuleList::const_iterator it = cite_engine_.begin();
3315 LayoutModuleList::const_iterator en = cite_engine_.end();
3316 for (; it != en; ++it)
3319 cite_engine_.push_back(engine);
3324 bool BufferParams::addCiteEngine(vector<string> const & engine)
3326 vector<string>::const_iterator it = engine.begin();
3327 vector<string>::const_iterator en = engine.end();
3329 for (; it != en; ++it)
3330 if (!addCiteEngine(*it))
3336 string const & BufferParams::defaultBiblioStyle() const
3338 map<string, string> const & bs = documentClass().defaultBiblioStyle();
3339 auto cit = bs.find(theCiteEnginesList.getTypeAsString(citeEngineType()));
3340 if (cit != bs.end())
3343 return empty_string();
3347 bool const & BufferParams::fullAuthorList() const
3349 return documentClass().fullAuthorList();
3353 string BufferParams::getCiteAlias(string const & s) const
3355 vector<string> commands =
3356 documentClass().citeCommands(citeEngineType());
3357 // If it is a real command, don't treat it as an alias
3358 if (find(commands.begin(), commands.end(), s) != commands.end())
3360 map<string,string> aliases = documentClass().citeCommandAliases();
3361 if (aliases.find(s) != aliases.end())
3367 void BufferParams::setCiteEngine(string const & engine)
3370 addCiteEngine(engine);
3374 void BufferParams::setCiteEngine(vector<string> const & engine)
3377 addCiteEngine(engine);
3381 vector<string> BufferParams::citeCommands() const
3383 static CitationStyle const default_style;
3384 vector<string> commands =
3385 documentClass().citeCommands(citeEngineType());
3386 if (commands.empty())
3387 commands.push_back(default_style.name);
3392 vector<CitationStyle> BufferParams::citeStyles() const
3394 static CitationStyle const default_style;
3395 vector<CitationStyle> styles =
3396 documentClass().citeStyles(citeEngineType());
3398 styles.push_back(default_style);
3403 string const BufferParams::bibtexCommand() const
3405 // Return document-specific setting if available
3406 if (bibtex_command != "default")
3407 return bibtex_command;
3409 // If we have "default" in document settings, consult the prefs
3410 // 1. Japanese (uses a specific processor)
3411 if (encoding().package() == Encoding::japanese) {
3412 if (lyxrc.jbibtex_command != "automatic")
3413 // Return the specified program, if "automatic" is not set
3414 return lyxrc.jbibtex_command;
3415 else if (!useBiblatex()) {
3416 // With classic BibTeX, return pbibtex, jbibtex, bibtex
3417 if (lyxrc.jbibtex_alternatives.find("pbibtex") != lyxrc.jbibtex_alternatives.end())
3419 if (lyxrc.jbibtex_alternatives.find("jbibtex") != lyxrc.jbibtex_alternatives.end())
3424 // 2. All other languages
3425 else if (lyxrc.bibtex_command != "automatic")
3426 // Return the specified program, if "automatic" is not set
3427 return lyxrc.bibtex_command;
3429 // 3. Automatic: find the most suitable for the current cite framework
3430 if (useBiblatex()) {
3431 // For Biblatex, we prefer biber (also for Japanese)
3432 // and fall back to bibtex8 and, as last resort, bibtex
3433 if (lyxrc.bibtex_alternatives.find("biber") != lyxrc.bibtex_alternatives.end())
3435 else if (lyxrc.bibtex_alternatives.find("bibtex8") != lyxrc.bibtex_alternatives.end())
3442 bool BufferParams::useBiblatex() const
3444 return theCiteEnginesList[citeEngine().list().front()]
3445 ->getCiteFramework() == "biblatex";
3449 void BufferParams::invalidateConverterCache() const
3451 pimpl_->isExportCacheValid = false;
3452 pimpl_->isViewCacheValid = false;