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 HSpace math_indentation;
346 PDFOptions pdfoptions;
347 LayoutFileIndex baseClass_;
348 FormatList exportableFormatList;
349 FormatList viewableFormatList;
350 bool isViewCacheValid;
351 bool isExportCacheValid;
355 BufferParams::Impl::Impl()
356 : defskip(VSpace::MEDSKIP), baseClass_(string("")),
357 isViewCacheValid(false), isExportCacheValid(false)
359 // set initial author
361 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
366 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
369 return new BufferParams::Impl(*ptr);
373 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
379 BufferParams::BufferParams()
382 setBaseClass(defaultBaseclass());
383 cite_engine_.push_back("basic");
384 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
386 paragraph_separation = ParagraphIndentSeparation;
387 is_math_indent = false;
388 math_indentation = "default";
389 quotes_style = InsetQuotesParams::EnglishQuotes;
390 dynamic_quotes = false;
391 fontsize = "default";
394 papersize = PAPER_DEFAULT;
395 orientation = ORIENTATION_PORTRAIT;
396 use_geometry = false;
397 biblio_style = "plain";
398 use_bibtopic = false;
401 save_transient_properties = true;
402 track_changes = false;
403 output_changes = false;
404 use_default_options = true;
405 maintain_unincluded_children = false;
408 language = default_language;
410 fonts_roman[0] = "default";
411 fonts_roman[1] = "default";
412 fonts_sans[0] = "default";
413 fonts_sans[1] = "default";
414 fonts_typewriter[0] = "default";
415 fonts_typewriter[1] = "default";
416 fonts_math[0] = "auto";
417 fonts_math[1] = "auto";
418 fonts_default_family = "default";
419 useNonTeXFonts = false;
420 use_microtype = false;
421 use_dash_ligatures = true;
422 fonts_expert_sc = false;
423 fonts_old_figures = false;
424 fonts_sans_scale[0] = 100;
425 fonts_sans_scale[1] = 100;
426 fonts_typewriter_scale[0] = 100;
427 fonts_typewriter_scale[1] = 100;
429 lang_package = "default";
430 graphics_driver = "default";
431 default_output_format = "default";
432 bibtex_command = "default";
433 index_command = "default";
436 listings_params = string();
437 pagestyle = "default";
438 suppress_date = false;
439 justification = true;
440 // no color is the default (white)
441 backgroundcolor = lyx::rgbFromHexName("#ffffff");
442 isbackgroundcolor = false;
443 // no color is the default (black)
444 fontcolor = lyx::rgbFromHexName("#000000");
446 // light gray is the default font color for greyed-out notes
447 notefontcolor = lyx::rgbFromHexName("#cccccc");
448 boxbgcolor = lyx::rgbFromHexName("#ff0000");
449 compressed = lyxrc.save_compressed;
450 for (int iter = 0; iter < 4; ++iter) {
451 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
452 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
455 indiceslist().addDefault(B_("Index"));
456 html_be_strict = false;
457 html_math_output = MathML;
458 html_math_img_scale = 1.0;
459 html_css_as_file = false;
460 display_pixel_ratio = 1.0;
465 // map current author
466 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
470 docstring BufferParams::B_(string const & l10n) const
472 LASSERT(language, return from_utf8(l10n));
473 return getMessages(language->code()).get(l10n);
477 BufferParams::Package BufferParams::use_package(std::string const & p) const
479 PackageMap::const_iterator it = use_packages.find(p);
480 if (it == use_packages.end())
486 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
492 map<string, string> const & BufferParams::auto_packages()
494 static map<string, string> packages;
495 if (packages.empty()) {
496 // We could have a race condition here that two threads
497 // discover an empty map at the same time and want to fill
498 // it, but that is no problem, since the same contents is
499 // filled in twice then. Having the locker inside the
500 // packages.empty() condition has the advantage that we
501 // don't need the mutex overhead for simple reading.
503 Mutex::Locker locker(&mutex);
504 // adding a package here implies a file format change!
505 packages["amsmath"] =
506 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
507 packages["amssymb"] =
508 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
510 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
512 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
513 packages["mathdots"] =
514 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
515 packages["mathtools"] =
516 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
518 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
519 packages["stackrel"] =
520 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
521 packages["stmaryrd"] =
522 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");
523 packages["undertilde"] =
524 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
530 bool BufferParams::useBibtopic() const
534 return (use_bibtopic || (!multibib.empty() && multibib != "child"));
538 AuthorList & BufferParams::authors()
540 return pimpl_->authorlist;
544 AuthorList const & BufferParams::authors() const
546 return pimpl_->authorlist;
550 void BufferParams::addAuthor(Author a)
552 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
556 BranchList & BufferParams::branchlist()
558 return pimpl_->branchlist;
562 BranchList const & BufferParams::branchlist() const
564 return pimpl_->branchlist;
568 IndicesList & BufferParams::indiceslist()
570 return pimpl_->indiceslist;
574 IndicesList const & BufferParams::indiceslist() const
576 return pimpl_->indiceslist;
580 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
582 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
583 return pimpl_->temp_bullets[index];
587 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
589 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
590 return pimpl_->temp_bullets[index];
594 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
596 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
597 return pimpl_->user_defined_bullets[index];
601 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
603 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
604 return pimpl_->user_defined_bullets[index];
608 Spacing & BufferParams::spacing()
610 return pimpl_->spacing;
614 Spacing const & BufferParams::spacing() const
616 return pimpl_->spacing;
620 PDFOptions & BufferParams::pdfoptions()
622 return pimpl_->pdfoptions;
626 PDFOptions const & BufferParams::pdfoptions() const
628 return pimpl_->pdfoptions;
632 HSpace const & BufferParams::getMathIndentation() const
634 return pimpl_->math_indentation;
638 void BufferParams::setMathIndentation(HSpace const & indent)
640 pimpl_->math_indentation = indent;
644 Length const & BufferParams::getParIndent() const
646 return pimpl_->parindent;
650 void BufferParams::setParIndent(Length const & indent)
652 pimpl_->parindent = indent;
656 VSpace const & BufferParams::getDefSkip() const
658 return pimpl_->defskip;
662 void BufferParams::setDefSkip(VSpace const & vs)
664 // DEFSKIP will cause an infinite loop
665 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
666 pimpl_->defskip = vs;
670 string BufferParams::readToken(Lexer & lex, string const & token,
671 FileName const & filepath)
675 if (token == "\\textclass") {
677 string const classname = lex.getString();
678 // if there exists a local layout file, ignore the system one
679 // NOTE: in this case, the textclass (.cls file) is assumed to
682 LayoutFileList & bcl = LayoutFileList::get();
683 if (!filepath.empty()) {
684 // If classname is an absolute path, the document is
685 // using a local layout file which could not be accessed
686 // by a relative path. In this case the path is correct
687 // even if the document was moved to a different
688 // location. However, we will have a problem if the
689 // document was generated on a different platform.
690 bool isabsolute = FileName::isAbsolute(classname);
691 string const classpath = onlyPath(classname);
692 string const path = isabsolute ? classpath
693 : FileName(addPath(filepath.absFileName(),
694 classpath)).realPath();
695 string const oldpath = isabsolute ? string()
696 : FileName(addPath(origin, classpath)).realPath();
697 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
699 // that returns non-empty if a "local" layout file is found.
701 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
702 from_utf8(filepath.absFileName())));
705 setBaseClass(onlyFileName(tcp));
707 setBaseClass(onlyFileName(classname));
708 // We assume that a tex class exists for local or unknown
709 // layouts so this warning, will only be given for system layouts.
710 if (!baseClass()->isTeXClassAvailable()) {
711 docstring const desc =
712 translateIfPossible(from_utf8(baseClass()->description()));
713 docstring const prereqs =
714 from_utf8(baseClass()->prerequisites());
715 docstring const msg =
716 bformat(_("The selected document class\n"
718 "requires external files that are not available.\n"
719 "The document class can still be used, but the\n"
720 "document cannot be compiled until the following\n"
721 "prerequisites are installed:\n"
723 "See section 3.1.2.2 (Class Availability) of the\n"
724 "User's Guide for more information."), desc, prereqs);
725 frontend::Alert::warning(_("Document class not available"),
728 } else if (token == "\\save_transient_properties") {
729 lex >> save_transient_properties;
730 } else if (token == "\\origin") {
732 origin = lex.getString();
733 string const sysdirprefix = "/systemlyxdir/";
734 if (prefixIs(origin, sysdirprefix)) {
736 if (inSystemDir(filepath, docsys))
737 origin.replace(0, sysdirprefix.length() - 1, docsys);
739 origin.replace(0, sysdirprefix.length() - 1,
740 package().system_support().absFileName());
742 } else if (token == "\\begin_preamble") {
744 } else if (token == "\\begin_local_layout") {
745 readLocalLayout(lex, false);
746 } else if (token == "\\begin_forced_local_layout") {
747 readLocalLayout(lex, true);
748 } else if (token == "\\begin_modules") {
750 } else if (token == "\\begin_removed_modules") {
751 readRemovedModules(lex);
752 } else if (token == "\\begin_includeonly") {
753 readIncludeonly(lex);
754 } else if (token == "\\maintain_unincluded_children") {
755 lex >> maintain_unincluded_children;
756 } else if (token == "\\options") {
758 options = lex.getString();
759 } else if (token == "\\use_default_options") {
760 lex >> use_default_options;
761 } else if (token == "\\master") {
763 master = lex.getString();
764 if (!filepath.empty() && FileName::isAbsolute(origin)) {
765 bool const isabs = FileName::isAbsolute(master);
766 FileName const abspath(isabs ? master : origin + master);
767 bool const moved = filepath != FileName(origin);
768 if (moved && abspath.exists()) {
769 docstring const path = isabs
771 : from_utf8(abspath.realPath());
772 docstring const refpath =
773 from_utf8(filepath.absFileName());
774 master = to_utf8(makeRelPath(path, refpath));
777 } else if (token == "\\suppress_date") {
778 lex >> suppress_date;
779 } else if (token == "\\justification") {
780 lex >> justification;
781 } else if (token == "\\language") {
783 } else if (token == "\\language_package") {
785 lang_package = lex.getString();
786 } else if (token == "\\inputencoding") {
788 } else if (token == "\\graphics") {
789 readGraphicsDriver(lex);
790 } else if (token == "\\default_output_format") {
791 lex >> default_output_format;
792 } else if (token == "\\bibtex_command") {
794 bibtex_command = lex.getString();
795 } else if (token == "\\index_command") {
797 index_command = lex.getString();
798 } else if (token == "\\fontencoding") {
800 fontenc = lex.getString();
801 } else if (token == "\\font_roman") {
802 lex >> fonts_roman[0];
803 lex >> fonts_roman[1];
804 } else if (token == "\\font_sans") {
805 lex >> fonts_sans[0];
806 lex >> fonts_sans[1];
807 } else if (token == "\\font_typewriter") {
808 lex >> fonts_typewriter[0];
809 lex >> fonts_typewriter[1];
810 } else if (token == "\\font_math") {
811 lex >> fonts_math[0];
812 lex >> fonts_math[1];
813 } else if (token == "\\font_default_family") {
814 lex >> fonts_default_family;
815 } else if (token == "\\use_non_tex_fonts") {
816 lex >> useNonTeXFonts;
817 } else if (token == "\\font_sc") {
818 lex >> fonts_expert_sc;
819 } else if (token == "\\font_osf") {
820 lex >> fonts_old_figures;
821 } else if (token == "\\font_sf_scale") {
822 lex >> fonts_sans_scale[0];
823 lex >> fonts_sans_scale[1];
824 } else if (token == "\\font_tt_scale") {
825 lex >> fonts_typewriter_scale[0];
826 lex >> fonts_typewriter_scale[1];
827 } else if (token == "\\font_cjk") {
829 } else if (token == "\\use_microtype") {
830 lex >> use_microtype;
831 } else if (token == "\\use_dash_ligatures") {
832 lex >> use_dash_ligatures;
833 } else if (token == "\\paragraph_separation") {
836 paragraph_separation = parseptranslator().find(parsep);
837 } else if (token == "\\paragraph_indentation") {
838 lex >> pimpl_->parindent;
839 } else if (token == "\\defskip") {
841 string const defskip = lex.getString();
842 pimpl_->defskip = VSpace(defskip);
843 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
845 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
846 } else if (token == "\\is_math_indent") {
847 lex >> is_math_indent;
848 } else if (token == "\\math_indentation") {
850 string math_indentation = lex.getString();
851 pimpl_->math_indentation = HSpace(math_indentation);
852 } else if (token == "\\quotes_style") {
855 quotes_style = quotesstyletranslator().find(qstyle);
856 } else if (token == "\\dynamic_quotes") {
857 lex >> dynamic_quotes;
858 } else if (token == "\\papersize") {
861 papersize = papersizetranslator().find(ppsize);
862 } else if (token == "\\use_geometry") {
864 } else if (token == "\\use_package") {
869 use_package(package, packagetranslator().find(use));
870 } else if (token == "\\cite_engine") {
872 vector<string> engine = getVectorFromString(lex.getString());
873 setCiteEngine(engine);
874 } else if (token == "\\cite_engine_type") {
877 cite_engine_type_ = theCiteEnginesList.getType(engine_type);
878 } else if (token == "\\biblio_style") {
880 biblio_style = lex.getString();
881 } else if (token == "\\biblio_options") {
883 biblio_opts = trim(lex.getString());
884 } else if (token == "\\biblatex_bibstyle") {
886 biblatex_bibstyle = trim(lex.getString());
887 } else if (token == "\\biblatex_citestyle") {
889 biblatex_citestyle = trim(lex.getString());
890 } else if (token == "\\use_bibtopic") {
892 } else if (token == "\\multibib") {
894 } else if (token == "\\use_indices") {
896 } else if (token == "\\tracking_changes") {
897 lex >> track_changes;
898 } else if (token == "\\output_changes") {
899 lex >> output_changes;
900 } else if (token == "\\branch") {
902 docstring branch = lex.getDocString();
903 branchlist().add(branch);
906 string const tok = lex.getString();
907 if (tok == "\\end_branch")
909 Branch * branch_ptr = branchlist().find(branch);
910 if (tok == "\\selected") {
913 branch_ptr->setSelected(lex.getInteger());
915 if (tok == "\\filename_suffix") {
918 branch_ptr->setFileNameSuffix(lex.getInteger());
920 if (tok == "\\color") {
922 string color = lex.getString();
924 branch_ptr->setColor(color);
925 // Update also the Color table:
927 color = lcolor.getX11Name(Color_background);
929 lcolor.setColor(to_utf8(branch), color);
932 } else if (token == "\\index") {
934 docstring index = lex.getDocString();
936 indiceslist().add(index);
939 string const tok = lex.getString();
940 if (tok == "\\end_index")
942 Index * index_ptr = indiceslist().find(index);
943 if (tok == "\\shortcut") {
945 shortcut = lex.getDocString();
947 index_ptr->setShortcut(shortcut);
949 if (tok == "\\color") {
951 string color = lex.getString();
953 index_ptr->setColor(color);
954 // Update also the Color table:
956 color = lcolor.getX11Name(Color_background);
958 if (!shortcut.empty())
959 lcolor.setColor(to_utf8(shortcut), color);
962 } else if (token == "\\author") {
964 istringstream ss(lex.getString());
968 } else if (token == "\\paperorientation") {
971 orientation = paperorientationtranslator().find(orient);
972 } else if (token == "\\backgroundcolor") {
974 backgroundcolor = lyx::rgbFromHexName(lex.getString());
975 isbackgroundcolor = true;
976 } else if (token == "\\fontcolor") {
978 fontcolor = lyx::rgbFromHexName(lex.getString());
980 } else if (token == "\\notefontcolor") {
982 string color = lex.getString();
983 notefontcolor = lyx::rgbFromHexName(color);
984 lcolor.setColor("notefontcolor", color);
985 } else if (token == "\\boxbgcolor") {
987 string color = lex.getString();
988 boxbgcolor = lyx::rgbFromHexName(color);
989 lcolor.setColor("boxbgcolor", color);
990 } else if (token == "\\paperwidth") {
992 } else if (token == "\\paperheight") {
994 } else if (token == "\\leftmargin") {
996 } else if (token == "\\topmargin") {
998 } else if (token == "\\rightmargin") {
1000 } else if (token == "\\bottommargin") {
1001 lex >> bottommargin;
1002 } else if (token == "\\headheight") {
1004 } else if (token == "\\headsep") {
1006 } else if (token == "\\footskip") {
1008 } else if (token == "\\columnsep") {
1010 } else if (token == "\\paperfontsize") {
1012 } else if (token == "\\papercolumns") {
1014 } else if (token == "\\listings_params") {
1017 listings_params = InsetListingsParams(par).params();
1018 } else if (token == "\\papersides") {
1021 sides = sidestranslator().find(psides);
1022 } else if (token == "\\paperpagestyle") {
1024 } else if (token == "\\bullet") {
1026 } else if (token == "\\bulletLaTeX") {
1027 readBulletsLaTeX(lex);
1028 } else if (token == "\\secnumdepth") {
1030 } else if (token == "\\tocdepth") {
1032 } else if (token == "\\spacing") {
1036 if (nspacing == "other") {
1039 spacing().set(spacetranslator().find(nspacing), tmp_val);
1040 } else if (token == "\\float_placement") {
1041 lex >> float_placement;
1043 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
1044 string toktmp = pdfoptions().readToken(lex, token);
1045 if (!toktmp.empty()) {
1046 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
1050 } else if (token == "\\html_math_output") {
1053 html_math_output = static_cast<MathOutput>(temp);
1054 } else if (token == "\\html_be_strict") {
1055 lex >> html_be_strict;
1056 } else if (token == "\\html_css_as_file") {
1057 lex >> html_css_as_file;
1058 } else if (token == "\\html_math_img_scale") {
1059 lex >> html_math_img_scale;
1060 } else if (token == "\\html_latex_start") {
1062 html_latex_start = lex.getString();
1063 } else if (token == "\\html_latex_end") {
1065 html_latex_end = lex.getString();
1066 } else if (token == "\\output_sync") {
1068 } else if (token == "\\output_sync_macro") {
1069 lex >> output_sync_macro;
1070 } else if (token == "\\use_refstyle") {
1071 lex >> use_refstyle;
1073 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1083 // Quote argument if it contains spaces
1084 string quoteIfNeeded(string const & str) {
1085 if (contains(str, ' '))
1086 return "\"" + str + "\"";
1092 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1094 // The top of the file is written by the buffer.
1095 // Prints out the buffer info into the .lyx file given by file
1097 os << "\\save_transient_properties "
1098 << convert<string>(save_transient_properties) << '\n';
1100 // the document directory (must end with a path separator)
1101 // realPath() is used to resolve symlinks, while addPath(..., "")
1102 // ensures a trailing path separator.
1104 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1105 string const sysdir = inSystemDir(FileName(filepath), docsys) ? docsys
1106 : addPath(package().system_support().realPath(), "");
1107 string const relpath =
1108 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1109 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1110 filepath = addPath("/systemlyxdir", relpath);
1111 else if (!save_transient_properties || !lyxrc.save_origin)
1112 filepath = "unavailable";
1113 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1116 os << "\\textclass "
1117 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1118 baseClass()->name()), "layout"))
1121 // then the preamble
1122 if (!preamble.empty()) {
1123 // remove '\n' from the end of preamble
1124 docstring const tmppreamble = rtrim(preamble, "\n");
1125 os << "\\begin_preamble\n"
1126 << to_utf8(tmppreamble)
1127 << "\n\\end_preamble\n";
1131 if (!options.empty()) {
1132 os << "\\options " << options << '\n';
1135 // use the class options defined in the layout?
1136 os << "\\use_default_options "
1137 << convert<string>(use_default_options) << "\n";
1139 // the master document
1140 if (!master.empty()) {
1141 os << "\\master " << master << '\n';
1145 if (!removed_modules_.empty()) {
1146 os << "\\begin_removed_modules" << '\n';
1147 list<string>::const_iterator it = removed_modules_.begin();
1148 list<string>::const_iterator en = removed_modules_.end();
1149 for (; it != en; ++it)
1151 os << "\\end_removed_modules" << '\n';
1155 if (!layout_modules_.empty()) {
1156 os << "\\begin_modules" << '\n';
1157 LayoutModuleList::const_iterator it = layout_modules_.begin();
1158 LayoutModuleList::const_iterator en = layout_modules_.end();
1159 for (; it != en; ++it)
1161 os << "\\end_modules" << '\n';
1165 if (!included_children_.empty()) {
1166 os << "\\begin_includeonly" << '\n';
1167 list<string>::const_iterator it = included_children_.begin();
1168 list<string>::const_iterator en = included_children_.end();
1169 for (; it != en; ++it)
1171 os << "\\end_includeonly" << '\n';
1173 os << "\\maintain_unincluded_children "
1174 << convert<string>(maintain_unincluded_children) << '\n';
1176 // local layout information
1177 docstring const local_layout = getLocalLayout(false);
1178 if (!local_layout.empty()) {
1179 // remove '\n' from the end
1180 docstring const tmplocal = rtrim(local_layout, "\n");
1181 os << "\\begin_local_layout\n"
1182 << to_utf8(tmplocal)
1183 << "\n\\end_local_layout\n";
1185 docstring const forced_local_layout = getLocalLayout(true);
1186 if (!forced_local_layout.empty()) {
1187 // remove '\n' from the end
1188 docstring const tmplocal = rtrim(forced_local_layout, "\n");
1189 os << "\\begin_forced_local_layout\n"
1190 << to_utf8(tmplocal)
1191 << "\n\\end_forced_local_layout\n";
1194 // then the text parameters
1195 if (language != ignore_language)
1196 os << "\\language " << language->lang() << '\n';
1197 os << "\\language_package " << lang_package
1198 << "\n\\inputencoding " << inputenc
1199 << "\n\\fontencoding " << fontenc
1200 << "\n\\font_roman \"" << fonts_roman[0]
1201 << "\" \"" << fonts_roman[1] << '"'
1202 << "\n\\font_sans \"" << fonts_sans[0]
1203 << "\" \"" << fonts_sans[1] << '"'
1204 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1205 << "\" \"" << fonts_typewriter[1] << '"'
1206 << "\n\\font_math \"" << fonts_math[0]
1207 << "\" \"" << fonts_math[1] << '"'
1208 << "\n\\font_default_family " << fonts_default_family
1209 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1210 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1211 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1212 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1213 << ' ' << fonts_sans_scale[1]
1214 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1215 << ' ' << fonts_typewriter_scale[1]
1217 if (!fonts_cjk.empty()) {
1218 os << "\\font_cjk " << fonts_cjk << '\n';
1220 os << "\\use_microtype " << convert<string>(use_microtype) << '\n';
1221 os << "\\use_dash_ligatures " << convert<string>(use_dash_ligatures) << '\n';
1222 os << "\\graphics " << graphics_driver << '\n';
1223 os << "\\default_output_format " << default_output_format << '\n';
1224 os << "\\output_sync " << output_sync << '\n';
1225 if (!output_sync_macro.empty())
1226 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1227 os << "\\bibtex_command " << bibtex_command << '\n';
1228 os << "\\index_command " << index_command << '\n';
1230 if (!float_placement.empty()) {
1231 os << "\\float_placement " << float_placement << '\n';
1233 os << "\\paperfontsize " << fontsize << '\n';
1235 spacing().writeFile(os);
1236 pdfoptions().writeFile(os);
1238 os << "\\papersize " << string_papersize[papersize]
1239 << "\n\\use_geometry " << convert<string>(use_geometry);
1240 map<string, string> const & packages = auto_packages();
1241 for (map<string, string>::const_iterator it = packages.begin();
1242 it != packages.end(); ++it)
1243 os << "\n\\use_package " << it->first << ' '
1244 << use_package(it->first);
1246 os << "\n\\cite_engine ";
1248 if (!cite_engine_.empty()) {
1249 LayoutModuleList::const_iterator be = cite_engine_.begin();
1250 LayoutModuleList::const_iterator en = cite_engine_.end();
1251 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1260 os << "\n\\cite_engine_type " << theCiteEnginesList.getTypeAsString(cite_engine_type_);
1262 if (!biblio_style.empty())
1263 os << "\n\\biblio_style " << biblio_style;
1264 if (!biblio_opts.empty())
1265 os << "\n\\biblio_options " << biblio_opts;
1266 if (!biblatex_bibstyle.empty())
1267 os << "\n\\biblatex_bibstyle " << biblatex_bibstyle;
1268 if (!biblatex_citestyle.empty())
1269 os << "\n\\biblatex_citestyle " << biblatex_citestyle;
1270 if (!multibib.empty())
1271 os << "\n\\multibib " << multibib;
1273 os << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1274 << "\n\\use_indices " << convert<string>(use_indices)
1275 << "\n\\paperorientation " << string_orientation[orientation]
1276 << "\n\\suppress_date " << convert<string>(suppress_date)
1277 << "\n\\justification " << convert<string>(justification)
1278 << "\n\\use_refstyle " << use_refstyle
1280 if (isbackgroundcolor == true)
1281 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1282 if (isfontcolor == true)
1283 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1284 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1285 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1286 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1287 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1289 BranchList::const_iterator it = branchlist().begin();
1290 BranchList::const_iterator end = branchlist().end();
1291 for (; it != end; ++it) {
1292 os << "\\branch " << to_utf8(it->branch())
1293 << "\n\\selected " << it->isSelected()
1294 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1295 << "\n\\color " << lyx::X11hexname(it->color())
1300 IndicesList::const_iterator iit = indiceslist().begin();
1301 IndicesList::const_iterator iend = indiceslist().end();
1302 for (; iit != iend; ++iit) {
1303 os << "\\index " << to_utf8(iit->index())
1304 << "\n\\shortcut " << to_utf8(iit->shortcut())
1305 << "\n\\color " << lyx::X11hexname(iit->color())
1310 if (!paperwidth.empty())
1311 os << "\\paperwidth "
1312 << VSpace(paperwidth).asLyXCommand() << '\n';
1313 if (!paperheight.empty())
1314 os << "\\paperheight "
1315 << VSpace(paperheight).asLyXCommand() << '\n';
1316 if (!leftmargin.empty())
1317 os << "\\leftmargin "
1318 << VSpace(leftmargin).asLyXCommand() << '\n';
1319 if (!topmargin.empty())
1320 os << "\\topmargin "
1321 << VSpace(topmargin).asLyXCommand() << '\n';
1322 if (!rightmargin.empty())
1323 os << "\\rightmargin "
1324 << VSpace(rightmargin).asLyXCommand() << '\n';
1325 if (!bottommargin.empty())
1326 os << "\\bottommargin "
1327 << VSpace(bottommargin).asLyXCommand() << '\n';
1328 if (!headheight.empty())
1329 os << "\\headheight "
1330 << VSpace(headheight).asLyXCommand() << '\n';
1331 if (!headsep.empty())
1333 << VSpace(headsep).asLyXCommand() << '\n';
1334 if (!footskip.empty())
1336 << VSpace(footskip).asLyXCommand() << '\n';
1337 if (!columnsep.empty())
1338 os << "\\columnsep "
1339 << VSpace(columnsep).asLyXCommand() << '\n';
1340 os << "\\secnumdepth " << secnumdepth
1341 << "\n\\tocdepth " << tocdepth
1342 << "\n\\paragraph_separation "
1343 << string_paragraph_separation[paragraph_separation];
1344 if (!paragraph_separation)
1345 os << "\n\\paragraph_indentation " << Lexer::quoteString(pimpl_->parindent.asString());
1347 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1348 os << "\n\\is_math_indent " << is_math_indent;
1349 if (is_math_indent && getMathIndentation().asLyXCommand() != "default")
1350 os << "\n\\math_indentation " << getMathIndentation().asLyXCommand();
1351 os << "\n\\quotes_style "
1352 << string_quotes_style[quotes_style]
1353 << "\n\\dynamic_quotes " << dynamic_quotes
1354 << "\n\\papercolumns " << columns
1355 << "\n\\papersides " << sides
1356 << "\n\\paperpagestyle " << pagestyle << '\n';
1357 if (!listings_params.empty())
1358 os << "\\listings_params \"" <<
1359 InsetListingsParams(listings_params).encodedString() << "\"\n";
1360 for (int i = 0; i < 4; ++i) {
1361 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1362 if (user_defined_bullet(i).getFont() != -1) {
1363 os << "\\bullet " << i << " "
1364 << user_defined_bullet(i).getFont() << " "
1365 << user_defined_bullet(i).getCharacter() << " "
1366 << user_defined_bullet(i).getSize() << "\n";
1370 os << "\\bulletLaTeX " << i << " \""
1371 << lyx::to_ascii(user_defined_bullet(i).getText())
1377 os << "\\tracking_changes "
1378 << (save_transient_properties ? convert<string>(track_changes) : "false")
1381 os << "\\output_changes "
1382 << (save_transient_properties ? convert<string>(output_changes) : "false")
1385 os << "\\html_math_output " << html_math_output << '\n'
1386 << "\\html_css_as_file " << html_css_as_file << '\n'
1387 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1389 if (html_math_img_scale != 1.0)
1390 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1391 if (!html_latex_start.empty())
1392 os << "\\html_latex_start " << html_latex_start << '\n';
1393 if (!html_latex_end.empty())
1394 os << "\\html_latex_end " << html_latex_end << '\n';
1396 os << pimpl_->authorlist;
1400 void BufferParams::validate(LaTeXFeatures & features) const
1402 features.require(documentClass().requires());
1404 if (columns > 1 && language->rightToLeft())
1405 features.require("rtloutputdblcol");
1407 if (output_changes) {
1408 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1409 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1410 LaTeXFeatures::isAvailable("xcolor");
1412 switch (features.runparams().flavor) {
1413 case OutputParams::LATEX:
1414 case OutputParams::DVILUATEX:
1416 features.require("ct-dvipost");
1417 features.require("dvipost");
1418 } else if (xcolorulem) {
1419 features.require("ct-xcolor-ulem");
1420 features.require("ulem");
1421 features.require("xcolor");
1423 features.require("ct-none");
1426 case OutputParams::LUATEX:
1427 case OutputParams::PDFLATEX:
1428 case OutputParams::XETEX:
1430 features.require("ct-xcolor-ulem");
1431 features.require("ulem");
1432 features.require("xcolor");
1433 // improves color handling in PDF output
1434 features.require("pdfcolmk");
1436 features.require("ct-none");
1444 // Floats with 'Here definitely' as default setting.
1445 if (float_placement.find('H') != string::npos)
1446 features.require("float");
1448 for (PackageMap::const_iterator it = use_packages.begin();
1449 it != use_packages.end(); ++it) {
1450 if (it->first == "amsmath") {
1451 // AMS Style is at document level
1452 if (it->second == package_on ||
1453 features.isProvided("amsmath"))
1454 features.require(it->first);
1455 } else if (it->second == package_on)
1456 features.require(it->first);
1459 // Document-level line spacing
1460 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1461 features.require("setspace");
1463 // the bullet shapes are buffer level not paragraph level
1464 // so they are tested here
1465 for (int i = 0; i < 4; ++i) {
1466 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1468 int const font = user_defined_bullet(i).getFont();
1470 int const c = user_defined_bullet(i).getCharacter();
1476 features.require("latexsym");
1478 } else if (font == 1) {
1479 features.require("amssymb");
1480 } else if (font >= 2 && font <= 5) {
1481 features.require("pifont");
1485 if (pdfoptions().use_hyperref) {
1486 features.require("hyperref");
1487 // due to interferences with babel and hyperref, the color package has to
1488 // be loaded after hyperref when hyperref is used with the colorlinks
1489 // option, see http://www.lyx.org/trac/ticket/5291
1490 if (pdfoptions().colorlinks)
1491 features.require("color");
1493 if (!listings_params.empty()) {
1494 // do not test validity because listings_params is
1495 // supposed to be valid
1497 InsetListingsParams(listings_params).separatedParams(true);
1498 // we can't support all packages, but we should load the color package
1499 if (par.find("\\color", 0) != string::npos)
1500 features.require("color");
1503 // some languages are only available via polyglossia
1504 if (features.hasPolyglossiaExclusiveLanguages())
1505 features.require("polyglossia");
1507 if (useNonTeXFonts && fontsMath() != "auto")
1508 features.require("unicode-math");
1511 features.require("microtype");
1513 if (!language->requires().empty())
1514 features.require(language->requires());
1518 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1519 FileName const & filepath) const
1521 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1522 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1523 // \RequirePackage to do so, rather than the normal \usepackage
1524 // Do not try to load any other package before the document class, unless you
1525 // have a thorough understanding of the LATEX internals and know exactly what you
1527 if (features.mustProvide("fix-cm"))
1528 os << "\\RequirePackage{fix-cm}\n";
1529 // Likewise for fixltx2e. If other packages conflict with this policy,
1530 // treat it as a package bug (and report it!)
1531 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1532 if (features.mustProvide("fixltx2e"))
1533 os << "\\RequirePackage{fixltx2e}\n";
1535 os << "\\documentclass";
1537 DocumentClass const & tclass = documentClass();
1539 ostringstream clsoptions; // the document class options.
1541 if (tokenPos(tclass.opt_fontsize(),
1542 '|', fontsize) >= 0) {
1543 // only write if existing in list (and not default)
1544 clsoptions << fontsize << "pt,";
1547 // all paper sizes except of A4, A5, B5 and the US sizes need the
1549 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1550 && papersize != PAPER_USLETTER
1551 && papersize != PAPER_USLEGAL
1552 && papersize != PAPER_USEXECUTIVE
1553 && papersize != PAPER_A4
1554 && papersize != PAPER_A5
1555 && papersize != PAPER_B5;
1557 if (!use_geometry) {
1558 switch (papersize) {
1560 clsoptions << "a4paper,";
1562 case PAPER_USLETTER:
1563 clsoptions << "letterpaper,";
1566 clsoptions << "a5paper,";
1569 clsoptions << "b5paper,";
1571 case PAPER_USEXECUTIVE:
1572 clsoptions << "executivepaper,";
1575 clsoptions << "legalpaper,";
1609 if (sides != tclass.sides()) {
1612 clsoptions << "oneside,";
1615 clsoptions << "twoside,";
1621 if (columns != tclass.columns()) {
1623 clsoptions << "twocolumn,";
1625 clsoptions << "onecolumn,";
1629 && orientation == ORIENTATION_LANDSCAPE)
1630 clsoptions << "landscape,";
1633 clsoptions << "fleqn,";
1635 // language should be a parameter to \documentclass
1636 if (language->babel() == "hebrew"
1637 && default_language->babel() != "hebrew")
1638 // This seems necessary
1639 features.useLanguage(default_language);
1641 ostringstream language_options;
1642 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1643 bool const use_polyglossia = features.usePolyglossia();
1644 bool const global = lyxrc.language_global_options;
1645 if (use_babel || (use_polyglossia && global)) {
1646 language_options << features.getBabelLanguages();
1647 if (!language->babel().empty()) {
1648 if (!language_options.str().empty())
1649 language_options << ',';
1650 language_options << language->babel();
1652 if (global && !features.needBabelLangOptions()
1653 && !language_options.str().empty())
1654 clsoptions << language_options.str() << ',';
1657 // the predefined options from the layout
1658 if (use_default_options && !tclass.options().empty())
1659 clsoptions << tclass.options() << ',';
1661 // the user-defined options
1662 if (!options.empty()) {
1663 clsoptions << options << ',';
1666 string strOptions(clsoptions.str());
1667 if (!strOptions.empty()) {
1668 strOptions = rtrim(strOptions, ",");
1670 os << '[' << from_utf8(strOptions) << ']';
1673 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1674 // end of \documentclass defs
1676 // if we use fontspec or newtxmath, we have to load the AMS packages here
1677 string const ams = features.loadAMSPackages();
1678 bool const ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1");
1679 bool const use_newtxmath =
1680 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1681 ot1, false, false) == "newtxmath";
1682 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1683 os << from_ascii(ams);
1685 if (useNonTeXFonts) {
1686 if (!features.isProvided("fontspec"))
1687 os << "\\usepackage{fontspec}\n";
1688 if (features.mustProvide("unicode-math")
1689 && features.isAvailable("unicode-math"))
1690 os << "\\usepackage{unicode-math}\n";
1693 // font selection must be done before loading fontenc.sty
1694 string const fonts = loadFonts(features);
1696 os << from_utf8(fonts);
1698 if (fonts_default_family != "default")
1699 os << "\\renewcommand{\\familydefault}{\\"
1700 << from_ascii(fonts_default_family) << "}\n";
1702 // set font encoding
1703 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1704 if (!useNonTeXFonts && !features.isProvided("fontenc")
1705 && main_font_encoding() != "default") {
1706 // get main font encodings
1707 vector<string> fontencs = font_encodings();
1708 // get font encodings of secondary languages
1709 features.getFontEncodings(fontencs);
1710 if (!fontencs.empty()) {
1711 os << "\\usepackage["
1712 << from_ascii(getStringFromVector(fontencs))
1717 // handle inputenc etc.
1718 writeEncodingPreamble(os, features);
1721 if (!features.runparams().includeall && !included_children_.empty()) {
1722 os << "\\includeonly{";
1723 list<string>::const_iterator it = included_children_.begin();
1724 list<string>::const_iterator en = included_children_.end();
1726 for (; it != en; ++it) {
1727 string incfile = *it;
1728 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1729 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1731 if (!features.runparams().nice)
1733 // \includeonly doesn't want an extension
1734 incfile = changeExtension(incfile, string());
1735 incfile = support::latex_path(incfile);
1736 if (!incfile.empty()) {
1739 os << from_utf8(incfile);
1746 if (!features.isProvided("geometry")
1747 && (use_geometry || nonstandard_papersize)) {
1748 odocstringstream ods;
1749 if (!getGraphicsDriver("geometry").empty())
1750 ods << getGraphicsDriver("geometry");
1751 if (orientation == ORIENTATION_LANDSCAPE)
1752 ods << ",landscape";
1753 switch (papersize) {
1755 if (!paperwidth.empty())
1756 ods << ",paperwidth="
1757 << from_ascii(paperwidth);
1758 if (!paperheight.empty())
1759 ods << ",paperheight="
1760 << from_ascii(paperheight);
1762 case PAPER_USLETTER:
1763 ods << ",letterpaper";
1766 ods << ",legalpaper";
1768 case PAPER_USEXECUTIVE:
1769 ods << ",executivepaper";
1858 docstring const g_options = trim(ods.str(), ",");
1859 os << "\\usepackage";
1860 if (!g_options.empty())
1861 os << '[' << g_options << ']';
1862 os << "{geometry}\n";
1863 // output this only if use_geometry is true
1865 os << "\\geometry{verbose";
1866 if (!topmargin.empty())
1867 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1868 if (!bottommargin.empty())
1869 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1870 if (!leftmargin.empty())
1871 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1872 if (!rightmargin.empty())
1873 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1874 if (!headheight.empty())
1875 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1876 if (!headsep.empty())
1877 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1878 if (!footskip.empty())
1879 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1880 if (!columnsep.empty())
1881 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1884 } else if (orientation == ORIENTATION_LANDSCAPE
1885 || papersize != PAPER_DEFAULT) {
1886 features.require("papersize");
1889 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1890 if (pagestyle == "fancy")
1891 os << "\\usepackage{fancyhdr}\n";
1892 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1895 // only output when the background color is not default
1896 if (isbackgroundcolor == true) {
1897 // only require color here, the background color will be defined
1898 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1900 features.require("color");
1901 features.require("pagecolor");
1904 // only output when the font color is not default
1905 if (isfontcolor == true) {
1906 // only require color here, the font color will be defined
1907 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1909 features.require("color");
1910 features.require("fontcolor");
1913 // Only if class has a ToC hierarchy
1914 if (tclass.hasTocLevels()) {
1915 if (secnumdepth != tclass.secnumdepth()) {
1916 os << "\\setcounter{secnumdepth}{"
1920 if (tocdepth != tclass.tocdepth()) {
1921 os << "\\setcounter{tocdepth}{"
1927 if (paragraph_separation) {
1928 // when skip separation
1929 switch (getDefSkip().kind()) {
1930 case VSpace::SMALLSKIP:
1931 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1933 case VSpace::MEDSKIP:
1934 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1936 case VSpace::BIGSKIP:
1937 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1939 case VSpace::LENGTH:
1940 os << "\\setlength{\\parskip}{"
1941 << from_utf8(getDefSkip().length().asLatexString())
1944 default: // should never happen // Then delete it.
1945 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1948 os << "\\setlength{\\parindent}{0pt}\n";
1950 // when separation by indentation
1951 // only output something when a width is given
1952 if (!getParIndent().empty()) {
1953 os << "\\setlength{\\parindent}{"
1954 << from_utf8(getParIndent().asLatexString())
1959 if (is_math_indent) {
1960 // when formula indentation
1961 // only output something when it is not the default
1962 if (getMathIndentation().asLyXCommand() != "default") {
1963 os << "\\setlength{\\mathindent}{"
1964 << from_utf8(getMathIndentation().asLatexCommand())
1969 // Now insert the LyX specific LaTeX commands...
1970 features.resolveAlternatives();
1971 features.expandMultiples();
1974 if (!output_sync_macro.empty())
1975 os << from_utf8(output_sync_macro) +"\n";
1976 else if (features.runparams().flavor == OutputParams::LATEX)
1977 os << "\\usepackage[active]{srcltx}\n";
1978 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1979 os << "\\synctex=-1\n";
1982 // The package options (via \PassOptionsToPackage)
1983 os << from_ascii(features.getPackageOptions());
1985 // due to interferences with babel and hyperref, the color package has to
1986 // be loaded (when it is not already loaded) before babel when hyperref
1987 // is used with the colorlinks option, see
1988 // http://www.lyx.org/trac/ticket/5291
1989 // we decided therefore to load color always before babel, see
1990 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1991 os << from_ascii(features.getColorOptions());
1993 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1994 // we have to call babel before
1996 && (features.isRequired("jurabib")
1997 || features.isRequired("hyperref")
1998 || features.isRequired("varioref")
1999 || features.isRequired("vietnamese")
2000 || features.isRequired("japanese"))) {
2001 os << features.getBabelPresettings();
2003 os << from_utf8(babelCall(language_options.str(),
2004 features.needBabelLangOptions())) + '\n';
2005 os << features.getBabelPostsettings();
2008 // The optional packages;
2009 os << from_ascii(features.getPackages());
2011 // Additional Indices
2012 if (features.isRequired("splitidx")) {
2013 IndicesList::const_iterator iit = indiceslist().begin();
2014 IndicesList::const_iterator iend = indiceslist().end();
2015 for (; iit != iend; ++iit) {
2016 os << "\\newindex{";
2017 os << escape(iit->shortcut());
2023 os << from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
2026 // * Hyperref manual: "Make sure it comes last of your loaded
2027 // packages, to give it a fighting chance of not being over-written,
2028 // since its job is to redefine many LaTeX commands."
2029 // * Email from Heiko Oberdiek: "It is usually better to load babel
2030 // before hyperref. Then hyperref has a chance to detect babel.
2031 // * Has to be loaded before the "LyX specific LaTeX commands" to
2032 // avoid errors with algorithm floats.
2033 // use hyperref explicitly if it is required
2034 if (features.isRequired("hyperref")) {
2035 OutputParams tmp_params = features.runparams();
2036 pdfoptions().writeLaTeX(tmp_params, os,
2037 features.isProvided("hyperref"));
2038 // correctly break URLs with hyperref and dvi output
2039 if (features.runparams().flavor == OutputParams::LATEX
2040 && features.isAvailable("breakurl"))
2041 os << "\\usepackage{breakurl}\n";
2042 } else if (features.isRequired("nameref"))
2043 // hyperref loads this automatically
2044 os << "\\usepackage{nameref}\n";
2046 // bibtopic needs to be loaded after hyperref.
2047 // the dot provides the aux file naming which LyX can detect.
2048 if (features.mustProvide("bibtopic"))
2049 os << "\\usepackage[dot]{bibtopic}\n";
2051 // Will be surrounded by \makeatletter and \makeatother when not empty
2052 otexstringstream atlyxpreamble;
2054 // Some macros LyX will need
2056 TexString tmppreamble = features.getMacros();
2057 if (!tmppreamble.str.empty())
2058 atlyxpreamble << "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2059 "LyX specific LaTeX commands.\n"
2060 << move(tmppreamble)
2063 // the text class specific preamble
2065 docstring tmppreamble = features.getTClassPreamble();
2066 if (!tmppreamble.empty())
2067 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2068 "Textclass specific LaTeX commands.\n"
2072 // suppress date if selected
2073 // use \@ifundefined because we cannot be sure that every document class
2074 // has a \date command
2076 atlyxpreamble << "\\@ifundefined{date}{}{\\date{}}\n";
2078 /* the user-defined preamble */
2079 if (!containsOnly(preamble, " \n\t")) {
2081 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2082 "User specified LaTeX commands.\n";
2084 // Check if the user preamble contains uncodable glyphs
2085 odocstringstream user_preamble;
2086 docstring uncodable_glyphs;
2087 Encoding const * const enc = features.runparams().encoding;
2089 for (size_t n = 0; n < preamble.size(); ++n) {
2090 char_type c = preamble[n];
2091 if (!enc->encodable(c)) {
2092 docstring const glyph(1, c);
2093 LYXERR0("Uncodable character '"
2095 << "' in user preamble!");
2096 uncodable_glyphs += glyph;
2097 if (features.runparams().dryrun) {
2098 user_preamble << "<" << _("LyX Warning: ")
2099 << _("uncodable character") << " '";
2100 user_preamble.put(c);
2101 user_preamble << "'>";
2104 user_preamble.put(c);
2107 user_preamble << preamble;
2109 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2110 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2111 frontend::Alert::warning(
2112 _("Uncodable character in user preamble"),
2114 _("The user preamble of your document contains glyphs "
2115 "that are unknown in the current document encoding "
2116 "(namely %1$s).\nThese glyphs are omitted "
2117 " from the output, which may result in "
2118 "incomplete output."
2119 "\n\nPlease select an appropriate "
2120 "document encoding\n"
2121 "(such as utf8) or change the "
2122 "preamble code accordingly."),
2125 atlyxpreamble << user_preamble.str() << '\n';
2128 // footmisc must be loaded after setspace
2129 // Load it here to avoid clashes with footmisc loaded in the user
2130 // preamble. For that reason we also pass the options via
2131 // \PassOptionsToPackage in getPreamble() and not here.
2132 if (features.mustProvide("footmisc"))
2133 atlyxpreamble << "\\usepackage{footmisc}\n";
2135 // subfig loads internally the LaTeX package "caption". As
2136 // caption is a very popular package, users will load it in
2137 // the preamble. Therefore we must load subfig behind the
2138 // user-defined preamble and check if the caption package was
2139 // loaded or not. For the case that caption is loaded before
2140 // subfig, there is the subfig option "caption=false". This
2141 // option also works when a koma-script class is used and
2142 // koma's own caption commands are used instead of caption. We
2143 // use \PassOptionsToPackage here because the user could have
2144 // already loaded subfig in the preamble.
2145 if (features.mustProvide("subfig"))
2146 atlyxpreamble << "\\@ifundefined{showcaptionsetup}{}{%\n"
2147 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2148 "\\usepackage{subfig}\n";
2150 // Itemize bullet settings need to be last in case the user
2151 // defines their own bullets that use a package included
2152 // in the user-defined preamble -- ARRae
2153 // Actually it has to be done much later than that
2154 // since some packages like frenchb make modifications
2155 // at \begin{document} time -- JMarc
2156 docstring bullets_def;
2157 for (int i = 0; i < 4; ++i) {
2158 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2159 if (bullets_def.empty())
2160 bullets_def += "\\AtBeginDocument{\n";
2161 bullets_def += " \\def\\labelitemi";
2163 // `i' is one less than the item to modify
2170 bullets_def += "ii";
2176 bullets_def += '{' +
2177 user_defined_bullet(i).getText()
2182 if (!bullets_def.empty())
2183 atlyxpreamble << bullets_def << "}\n\n";
2185 if (!atlyxpreamble.empty())
2186 os << "\n\\makeatletter\n"
2187 << atlyxpreamble.release()
2188 << "\\makeatother\n\n";
2190 // We try to load babel late, in case it interferes with other packages.
2191 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2192 // called after babel, though.
2193 if (use_babel && !features.isRequired("jurabib")
2194 && !features.isRequired("hyperref")
2195 && !features.isRequired("varioref")
2196 && !features.isRequired("vietnamese")
2197 && !features.isRequired("japanese")) {
2198 os << features.getBabelPresettings();
2200 os << from_utf8(babelCall(language_options.str(),
2201 features.needBabelLangOptions())) + '\n';
2202 os << features.getBabelPostsettings();
2204 if (features.isRequired("bicaption"))
2205 os << "\\usepackage{bicaption}\n";
2206 if (!listings_params.empty() || features.mustProvide("listings"))
2207 os << "\\usepackage{listings}\n";
2208 if (!listings_params.empty()) {
2210 // do not test validity because listings_params is
2211 // supposed to be valid
2213 InsetListingsParams(listings_params).separatedParams(true);
2214 os << from_utf8(par);
2218 // xunicode only needs to be loaded if tipa is used
2219 // (the rest is obsoleted by the new TU encoding).
2220 // It needs to be loaded at least after amsmath, amssymb,
2221 // esint and the other packages that provide special glyphs
2222 if (features.mustProvide("tipa") && useNonTeXFonts) {
2223 // The package officially only supports XeTeX, but also works
2224 // with LuaTeX. Thus we work around its XeTeX test.
2225 if (features.runparams().flavor != OutputParams::XETEX) {
2226 os << "% Pretend to xunicode that we are XeTeX\n"
2227 << "\\def\\XeTeXpicfile{}\n";
2229 os << "\\usepackage{xunicode}\n";
2232 // Polyglossia must be loaded last ...
2233 if (use_polyglossia) {
2235 os << "\\usepackage{polyglossia}\n";
2236 // set the main language
2237 os << "\\setdefaultlanguage";
2238 if (!language->polyglossiaOpts().empty())
2239 os << "[" << from_ascii(language->polyglossiaOpts()) << "]";
2240 os << "{" << from_ascii(language->polyglossia()) << "}\n";
2241 // now setup the other languages
2242 set<string> const polylangs =
2243 features.getPolyglossiaLanguages();
2244 for (set<string>::const_iterator mit = polylangs.begin();
2245 mit != polylangs.end() ; ++mit) {
2246 // We do not output the options here; they are output in
2247 // the language switch commands. This is safer if multiple
2248 // varieties are used.
2249 if (*mit == language->polyglossia())
2251 os << "\\setotherlanguage";
2252 os << "{" << from_ascii(*mit) << "}\n";
2256 // ... but before biblatex (see #7065)
2257 if (features.mustProvide("biblatex")) {
2260 os << "\\usepackage";
2261 if (!biblatex_bibstyle.empty()
2262 && (biblatex_bibstyle == biblatex_citestyle)) {
2263 opts = "style=" + biblatex_bibstyle;
2266 if (!biblatex_bibstyle.empty()) {
2267 opts = "bibstyle=" + biblatex_bibstyle;
2270 if (!biblatex_citestyle.empty()) {
2271 opts += delim + "citestyle=" + biblatex_citestyle;
2275 if (!multibib.empty() && multibib != "child") {
2276 opts += delim + "refsection=" + multibib;
2279 if (bibtexCommand() == "bibtex8"
2280 || prefixIs(bibtexCommand(), "bibtex8 ")) {
2281 opts += delim + "backend=bibtex8";
2283 } else if (bibtexCommand() == "bibtex"
2284 || prefixIs(bibtexCommand(), "bibtex ")) {
2285 opts += delim + "backend=bibtex";
2288 if (!biblio_opts.empty())
2289 opts += delim + biblio_opts;
2291 os << "[" << opts << "]";
2292 os << "{biblatex}\n";
2296 // Load custom language package here
2297 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2298 if (lang_package == "default")
2299 os << from_utf8(lyxrc.language_custom_package);
2301 os << from_utf8(lang_package);
2305 docstring const i18npreamble =
2306 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2307 if (!i18npreamble.empty())
2308 os << i18npreamble + '\n';
2314 void BufferParams::useClassDefaults()
2316 DocumentClass const & tclass = documentClass();
2318 sides = tclass.sides();
2319 columns = tclass.columns();
2320 pagestyle = tclass.pagestyle();
2321 use_default_options = true;
2322 // Only if class has a ToC hierarchy
2323 if (tclass.hasTocLevels()) {
2324 secnumdepth = tclass.secnumdepth();
2325 tocdepth = tclass.tocdepth();
2330 bool BufferParams::hasClassDefaults() const
2332 DocumentClass const & tclass = documentClass();
2334 return sides == tclass.sides()
2335 && columns == tclass.columns()
2336 && pagestyle == tclass.pagestyle()
2337 && use_default_options
2338 && secnumdepth == tclass.secnumdepth()
2339 && tocdepth == tclass.tocdepth();
2343 DocumentClass const & BufferParams::documentClass() const
2349 DocumentClassConstPtr BufferParams::documentClassPtr() const
2355 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2357 // evil, but this function is evil
2358 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2359 invalidateConverterCache();
2363 bool BufferParams::setBaseClass(string const & classname)
2365 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2366 LayoutFileList & bcl = LayoutFileList::get();
2367 if (!bcl.haveClass(classname)) {
2369 bformat(_("The layout file:\n"
2371 "could not be found. A default textclass with default\n"
2372 "layouts will be used. LyX will not be able to produce\n"
2374 from_utf8(classname));
2375 frontend::Alert::error(_("Document class not found"), s);
2376 bcl.addEmptyClass(classname);
2379 bool const success = bcl[classname].load();
2382 bformat(_("Due to some error in it, the layout file:\n"
2384 "could not be loaded. A default textclass with default\n"
2385 "layouts will be used. LyX will not be able to produce\n"
2387 from_utf8(classname));
2388 frontend::Alert::error(_("Could not load class"), s);
2389 bcl.addEmptyClass(classname);
2392 pimpl_->baseClass_ = classname;
2393 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2398 LayoutFile const * BufferParams::baseClass() const
2400 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2401 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2407 LayoutFileIndex const & BufferParams::baseClassID() const
2409 return pimpl_->baseClass_;
2413 void BufferParams::makeDocumentClass(bool const clone)
2418 invalidateConverterCache();
2419 LayoutModuleList mods;
2420 LayoutModuleList ces;
2421 LayoutModuleList::iterator it = layout_modules_.begin();
2422 LayoutModuleList::iterator en = layout_modules_.end();
2423 for (; it != en; ++it)
2424 mods.push_back(*it);
2426 it = cite_engine_.begin();
2427 en = cite_engine_.end();
2428 for (; it != en; ++it)
2431 doc_class_ = getDocumentClass(*baseClass(), mods, ces, clone);
2433 TextClass::ReturnValues success = TextClass::OK;
2434 if (!forced_local_layout_.empty())
2435 success = doc_class_->read(to_utf8(forced_local_layout_),
2437 if (!local_layout_.empty() &&
2438 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2439 success = doc_class_->read(to_utf8(local_layout_), TextClass::MODULE);
2440 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2441 docstring const msg = _("Error reading internal layout information");
2442 frontend::Alert::warning(_("Read Error"), msg);
2447 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2449 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2453 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2455 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2459 docstring BufferParams::getLocalLayout(bool forced) const
2462 return from_utf8(doc_class_->forcedLayouts());
2464 return local_layout_;
2468 void BufferParams::setLocalLayout(docstring const & layout, bool forced)
2471 forced_local_layout_ = layout;
2473 local_layout_ = layout;
2477 bool BufferParams::addLayoutModule(string const & modName)
2479 LayoutModuleList::const_iterator it = layout_modules_.begin();
2480 LayoutModuleList::const_iterator end = layout_modules_.end();
2481 for (; it != end; ++it)
2484 layout_modules_.push_back(modName);
2489 string BufferParams::bufferFormat() const
2491 return documentClass().outputFormat();
2495 bool BufferParams::isExportable(string const & format, bool need_viewable) const
2497 FormatList const & formats = exportableFormats(need_viewable);
2498 FormatList::const_iterator fit = formats.begin();
2499 FormatList::const_iterator end = formats.end();
2500 for (; fit != end ; ++fit) {
2501 if ((*fit)->name() == format)
2508 FormatList const & BufferParams::exportableFormats(bool only_viewable) const
2510 FormatList & cached = only_viewable ?
2511 pimpl_->viewableFormatList : pimpl_->exportableFormatList;
2512 bool & valid = only_viewable ?
2513 pimpl_->isViewCacheValid : pimpl_->isExportCacheValid;
2517 vector<string> const backs = backends();
2518 set<string> excludes;
2519 if (useNonTeXFonts) {
2520 excludes.insert("latex");
2521 excludes.insert("pdflatex");
2524 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2525 for (vector<string>::const_iterator it = backs.begin() + 1;
2526 it != backs.end(); ++it) {
2527 FormatList r = theConverters().getReachable(*it, only_viewable,
2529 result.insert(result.end(), r.begin(), r.end());
2531 sort(result.begin(), result.end(), Format::formatSorter);
2538 vector<string> BufferParams::backends() const
2541 string const buffmt = bufferFormat();
2543 // FIXME: Don't hardcode format names here, but use a flag
2544 if (buffmt == "latex") {
2545 if (encoding().package() == Encoding::japanese)
2546 v.push_back("platex");
2548 if (!useNonTeXFonts) {
2549 v.push_back("pdflatex");
2550 v.push_back("latex");
2552 v.push_back("xetex");
2553 v.push_back("luatex");
2554 v.push_back("dviluatex");
2557 v.push_back(buffmt);
2559 v.push_back("xhtml");
2560 v.push_back("text");
2566 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2568 string const dformat = (format.empty() || format == "default") ?
2569 getDefaultOutputFormat() : format;
2570 DefaultFlavorCache::const_iterator it =
2571 default_flavors_.find(dformat);
2573 if (it != default_flavors_.end())
2576 OutputParams::FLAVOR result = OutputParams::LATEX;
2578 // FIXME It'd be better not to hardcode this, but to do
2579 // something with formats.
2580 if (dformat == "xhtml")
2581 result = OutputParams::HTML;
2582 else if (dformat == "text")
2583 result = OutputParams::TEXT;
2584 else if (dformat == "lyx")
2585 result = OutputParams::LYX;
2586 else if (dformat == "pdflatex")
2587 result = OutputParams::PDFLATEX;
2588 else if (dformat == "xetex")
2589 result = OutputParams::XETEX;
2590 else if (dformat == "luatex")
2591 result = OutputParams::LUATEX;
2592 else if (dformat == "dviluatex")
2593 result = OutputParams::DVILUATEX;
2595 // Try to determine flavor of default output format
2596 vector<string> backs = backends();
2597 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2598 // Get shortest path to format
2599 Graph::EdgePath path;
2600 for (vector<string>::const_iterator it = backs.begin();
2601 it != backs.end(); ++it) {
2602 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2603 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2608 result = theConverters().getFlavor(path);
2611 // cache this flavor
2612 default_flavors_[dformat] = result;
2617 string BufferParams::getDefaultOutputFormat() const
2619 if (!default_output_format.empty()
2620 && default_output_format != "default")
2621 return default_output_format;
2623 || encoding().package() == Encoding::japanese) {
2624 FormatList const & formats = exportableFormats(true);
2625 if (formats.empty())
2627 // return the first we find
2628 return formats.front()->name();
2631 return lyxrc.default_otf_view_format;
2632 return lyxrc.default_view_format;
2635 Font const BufferParams::getFont() const
2637 FontInfo f = documentClass().defaultfont();
2638 if (fonts_default_family == "rmdefault")
2639 f.setFamily(ROMAN_FAMILY);
2640 else if (fonts_default_family == "sfdefault")
2641 f.setFamily(SANS_FAMILY);
2642 else if (fonts_default_family == "ttdefault")
2643 f.setFamily(TYPEWRITER_FAMILY);
2644 return Font(f, language);
2648 InsetQuotesParams::QuoteStyle BufferParams::getQuoteStyle(string const & qs) const
2650 return quotesstyletranslator().find(qs);
2654 bool BufferParams::isLatex() const
2656 return documentClass().outputType() == LATEX;
2660 bool BufferParams::isLiterate() const
2662 return documentClass().outputType() == LITERATE;
2666 bool BufferParams::isDocBook() const
2668 return documentClass().outputType() == DOCBOOK;
2672 void BufferParams::readPreamble(Lexer & lex)
2674 if (lex.getString() != "\\begin_preamble")
2675 lyxerr << "Error (BufferParams::readPreamble):"
2676 "consistency check failed." << endl;
2678 preamble = lex.getLongString(from_ascii("\\end_preamble"));
2682 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2684 string const expected = forced ? "\\begin_forced_local_layout" :
2685 "\\begin_local_layout";
2686 if (lex.getString() != expected)
2687 lyxerr << "Error (BufferParams::readLocalLayout):"
2688 "consistency check failed." << endl;
2691 forced_local_layout_ =
2692 lex.getLongString(from_ascii("\\end_forced_local_layout"));
2694 local_layout_ = lex.getLongString(from_ascii("\\end_local_layout"));
2698 bool BufferParams::setLanguage(string const & lang)
2700 Language const *new_language = languages.getLanguage(lang);
2701 if (!new_language) {
2702 // Language lang was not found
2705 language = new_language;
2710 void BufferParams::readLanguage(Lexer & lex)
2712 if (!lex.next()) return;
2714 string const tmptok = lex.getString();
2716 // check if tmptok is part of tex_babel in tex-defs.h
2717 if (!setLanguage(tmptok)) {
2718 // Language tmptok was not found
2719 language = default_language;
2720 lyxerr << "Warning: Setting language `"
2721 << tmptok << "' to `" << language->lang()
2727 void BufferParams::readGraphicsDriver(Lexer & lex)
2732 string const tmptok = lex.getString();
2733 // check if tmptok is part of tex_graphics in tex_defs.h
2736 string const test = tex_graphics[n++];
2738 if (test == tmptok) {
2739 graphics_driver = tmptok;
2744 "Warning: graphics driver `$$Token' not recognized!\n"
2745 " Setting graphics driver to `default'.\n");
2746 graphics_driver = "default";
2753 void BufferParams::readBullets(Lexer & lex)
2758 int const index = lex.getInteger();
2760 int temp_int = lex.getInteger();
2761 user_defined_bullet(index).setFont(temp_int);
2762 temp_bullet(index).setFont(temp_int);
2764 user_defined_bullet(index).setCharacter(temp_int);
2765 temp_bullet(index).setCharacter(temp_int);
2767 user_defined_bullet(index).setSize(temp_int);
2768 temp_bullet(index).setSize(temp_int);
2772 void BufferParams::readBulletsLaTeX(Lexer & lex)
2774 // The bullet class should be able to read this.
2777 int const index = lex.getInteger();
2779 docstring const temp_str = lex.getDocString();
2781 user_defined_bullet(index).setText(temp_str);
2782 temp_bullet(index).setText(temp_str);
2786 void BufferParams::readModules(Lexer & lex)
2788 if (!lex.eatLine()) {
2789 lyxerr << "Error (BufferParams::readModules):"
2790 "Unexpected end of input." << endl;
2794 string mod = lex.getString();
2795 if (mod == "\\end_modules")
2797 addLayoutModule(mod);
2803 void BufferParams::readRemovedModules(Lexer & lex)
2805 if (!lex.eatLine()) {
2806 lyxerr << "Error (BufferParams::readRemovedModules):"
2807 "Unexpected end of input." << endl;
2811 string mod = lex.getString();
2812 if (mod == "\\end_removed_modules")
2814 removed_modules_.push_back(mod);
2817 // now we want to remove any removed modules that were previously
2818 // added. normally, that will be because default modules were added in
2819 // setBaseClass(), which gets called when \textclass is read at the
2820 // start of the read.
2821 list<string>::const_iterator rit = removed_modules_.begin();
2822 list<string>::const_iterator const ren = removed_modules_.end();
2823 for (; rit != ren; ++rit) {
2824 LayoutModuleList::iterator const mit = layout_modules_.begin();
2825 LayoutModuleList::iterator const men = layout_modules_.end();
2826 LayoutModuleList::iterator found = find(mit, men, *rit);
2829 layout_modules_.erase(found);
2834 void BufferParams::readIncludeonly(Lexer & lex)
2836 if (!lex.eatLine()) {
2837 lyxerr << "Error (BufferParams::readIncludeonly):"
2838 "Unexpected end of input." << endl;
2842 string child = lex.getString();
2843 if (child == "\\end_includeonly")
2845 included_children_.push_back(child);
2851 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2853 switch (papersize) {
2855 // could be anything, so don't guess
2857 case PAPER_CUSTOM: {
2858 if (purpose == XDVI && !paperwidth.empty() &&
2859 !paperheight.empty()) {
2860 // heightxwidth<unit>
2861 string first = paperwidth;
2862 string second = paperheight;
2863 if (orientation == ORIENTATION_LANDSCAPE)
2866 return first.erase(first.length() - 2)
2872 // dvips and dvipdfm do not know this
2873 if (purpose == DVIPS || purpose == DVIPDFM)
2877 if (purpose == DVIPS || purpose == DVIPDFM)
2881 if (purpose == DVIPS || purpose == DVIPDFM)
2891 if (purpose == DVIPS || purpose == DVIPDFM)
2895 if (purpose == DVIPS || purpose == DVIPDFM)
2899 if (purpose == DVIPS || purpose == DVIPDFM)
2903 if (purpose == DVIPS || purpose == DVIPDFM)
2907 if (purpose == DVIPS || purpose == DVIPDFM)
2911 // dvipdfm does not know this
2912 if (purpose == DVIPDFM)
2916 if (purpose == DVIPDFM)
2920 if (purpose == DVIPS || purpose == DVIPDFM)
2924 if (purpose == DVIPS || purpose == DVIPDFM)
2928 if (purpose == DVIPS || purpose == DVIPDFM)
2932 if (purpose == DVIPS || purpose == DVIPDFM)
2936 if (purpose == DVIPS || purpose == DVIPDFM)
2940 if (purpose == DVIPS || purpose == DVIPDFM)
2944 if (purpose == DVIPS || purpose == DVIPDFM)
2948 if (purpose == DVIPS || purpose == DVIPDFM)
2952 if (purpose == DVIPS || purpose == DVIPDFM)
2956 if (purpose == DVIPS || purpose == DVIPDFM)
2960 if (purpose == DVIPS || purpose == DVIPDFM)
2964 if (purpose == DVIPS || purpose == DVIPDFM)
2968 if (purpose == DVIPS || purpose == DVIPDFM)
2972 if (purpose == DVIPS || purpose == DVIPDFM)
2976 if (purpose == DVIPS || purpose == DVIPDFM)
2979 case PAPER_USEXECUTIVE:
2980 // dvipdfm does not know this
2981 if (purpose == DVIPDFM)
2986 case PAPER_USLETTER:
2988 if (purpose == XDVI)
2995 string const BufferParams::dvips_options() const
2999 // If the class loads the geometry package, we do not know which
3000 // paper size is used, since we do not set it (bug 7013).
3001 // Therefore we must not specify any argument here.
3002 // dvips gets the correct paper size via DVI specials in this case
3003 // (if the class uses the geometry package correctly).
3004 if (documentClass().provides("geometry"))
3008 && papersize == PAPER_CUSTOM
3009 && !lyxrc.print_paper_dimension_flag.empty()
3010 && !paperwidth.empty()
3011 && !paperheight.empty()) {
3012 // using a custom papersize
3013 result = lyxrc.print_paper_dimension_flag;
3014 result += ' ' + paperwidth;
3015 result += ',' + paperheight;
3017 string const paper_option = paperSizeName(DVIPS);
3018 if (!paper_option.empty() && (paper_option != "letter" ||
3019 orientation != ORIENTATION_LANDSCAPE)) {
3020 // dvips won't accept -t letter -t landscape.
3021 // In all other cases, include the paper size
3023 result = lyxrc.print_paper_flag;
3024 result += ' ' + paper_option;
3027 if (orientation == ORIENTATION_LANDSCAPE &&
3028 papersize != PAPER_CUSTOM)
3029 result += ' ' + lyxrc.print_landscape_flag;
3034 string const BufferParams::main_font_encoding() const
3036 return font_encodings().empty() ? "default" : font_encodings().back();
3040 vector<string> const BufferParams::font_encodings() const
3042 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
3044 vector<string> fontencs;
3046 // "default" means "no explicit font encoding"
3047 if (doc_fontenc != "default") {
3048 fontencs = getVectorFromString(doc_fontenc);
3049 if (!language->fontenc().empty()
3050 && ascii_lowercase(language->fontenc()) != "none") {
3051 vector<string> fencs = getVectorFromString(language->fontenc());
3052 vector<string>::const_iterator fit = fencs.begin();
3053 for (; fit != fencs.end(); ++fit) {
3054 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
3055 fontencs.push_back(*fit);
3064 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
3066 // suppress the babel call if there is no BabelName defined
3067 // for the document language in the lib/languages file and if no
3068 // other languages are used (lang_opts is then empty)
3069 if (lang_opts.empty())
3071 // either a specific language (AsBabelOptions setting in
3072 // lib/languages) or the prefs require the languages to
3073 // be submitted to babel itself (not the class).
3075 return "\\usepackage[" + lang_opts + "]{babel}";
3076 return "\\usepackage{babel}";
3080 docstring BufferParams::getGraphicsDriver(string const & package) const
3084 if (package == "geometry") {
3085 if (graphics_driver == "dvips"
3086 || graphics_driver == "dvipdfm"
3087 || graphics_driver == "pdftex"
3088 || graphics_driver == "vtex")
3089 result = from_ascii(graphics_driver);
3090 else if (graphics_driver == "dvipdfmx")
3091 result = from_ascii("dvipdfm");
3098 void BufferParams::writeEncodingPreamble(otexstream & os,
3099 LaTeXFeatures & features) const
3101 // XeTeX/LuaTeX: (see also #9740)
3102 // With Unicode fonts we use utf8-plain without encoding package.
3103 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
3104 // XeTeX must use ASCII encoding (see Buffer.cpp),
3105 // for LuaTeX, we load "luainputenc" (see below).
3106 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
3109 if (inputenc == "auto") {
3110 string const doc_encoding =
3111 language->encoding()->latexName();
3112 Encoding::Package const package =
3113 language->encoding()->package();
3115 // Create list of inputenc options:
3116 set<string> encodings;
3117 // luainputenc fails with more than one encoding
3118 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
3119 // list all input encodings used in the document
3120 encodings = features.getEncodingSet(doc_encoding);
3122 // If the "japanese" package (i.e. pLaTeX) is used,
3123 // inputenc must be omitted.
3124 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
3125 if ((!encodings.empty() || package == Encoding::inputenc)
3126 && !features.isRequired("japanese")
3127 && !features.isProvided("inputenc")) {
3128 os << "\\usepackage[";
3129 set<string>::const_iterator it = encodings.begin();
3130 set<string>::const_iterator const end = encodings.end();
3132 os << from_ascii(*it);
3135 for (; it != end; ++it)
3136 os << ',' << from_ascii(*it);
3137 if (package == Encoding::inputenc) {
3138 if (!encodings.empty())
3140 os << from_ascii(doc_encoding);
3142 if (features.runparams().flavor == OutputParams::LUATEX
3143 || features.runparams().flavor == OutputParams::DVILUATEX)
3144 os << "]{luainputenc}\n";
3146 os << "]{inputenc}\n";
3148 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3149 if (language->encoding()->name() == "utf8-cjk"
3150 && LaTeXFeatures::isAvailable("CJKutf8"))
3151 os << "\\usepackage{CJKutf8}\n";
3153 os << "\\usepackage{CJK}\n";
3155 } else if (inputenc != "default") {
3156 switch (encoding().package()) {
3157 case Encoding::none:
3158 case Encoding::japanese:
3160 case Encoding::inputenc:
3161 // do not load inputenc if japanese is used
3162 // or if the class provides inputenc
3163 if (features.isRequired("japanese")
3164 || features.isProvided("inputenc"))
3166 os << "\\usepackage[" << from_ascii(encoding().latexName());
3167 if (features.runparams().flavor == OutputParams::LUATEX
3168 || features.runparams().flavor == OutputParams::DVILUATEX)
3169 os << "]{luainputenc}\n";
3171 os << "]{inputenc}\n";
3174 if (encoding().name() == "utf8-cjk"
3175 && LaTeXFeatures::isAvailable("CJKutf8"))
3176 os << "\\usepackage{CJKutf8}\n";
3178 os << "\\usepackage{CJK}\n";
3181 // Load the CJK package if needed by a secondary language.
3182 // If the main encoding is some variant of UTF8, use CJKutf8.
3183 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3184 if (encoding().iconvName() == "UTF-8"
3185 && LaTeXFeatures::isAvailable("CJKutf8"))
3186 os << "\\usepackage{CJKutf8}\n";
3188 os << "\\usepackage{CJK}\n";
3194 string const BufferParams::parseFontName(string const & name) const
3196 string mangled = name;
3197 size_t const idx = mangled.find('[');
3198 if (idx == string::npos || idx == 0)
3201 return mangled.substr(0, idx - 1);
3205 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3207 if (fontsRoman() == "default" && fontsSans() == "default"
3208 && fontsTypewriter() == "default"
3209 && (fontsMath() == "default" || fontsMath() == "auto"))
3215 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3216 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3217 * Mapping=tex-text option assures TeX ligatures (such as "--")
3218 * are resolved. Note that tt does not use these ligatures.
3220 * -- add more GUI options?
3221 * -- add more fonts (fonts for other scripts)
3222 * -- if there's a way to find out if a font really supports
3223 * OldStyle, enable/disable the widget accordingly.
3225 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3226 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3227 // However, until v.2 (2010/07/11) fontspec only knew
3228 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3229 // was introduced for both XeTeX and LuaTeX (LuaTeX
3230 // didn't understand "Mapping=tex-text", while XeTeX
3231 // understood both. With most recent versions, both
3232 // variants are understood by both engines. However,
3233 // we want to provide support for at least TeXLive 2009
3234 // (for XeTeX; LuaTeX is only supported as of v.2)
3235 string const texmapping =
3236 (features.runparams().flavor == OutputParams::XETEX) ?
3237 "Mapping=tex-text" : "Ligatures=TeX";
3238 if (fontsRoman() != "default") {
3239 os << "\\setmainfont[" << texmapping;
3240 if (fonts_old_figures)
3241 os << ",Numbers=OldStyle";
3242 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3244 if (fontsSans() != "default") {
3245 string const sans = parseFontName(fontsSans());
3246 if (fontsSansScale() != 100)
3247 os << "\\setsansfont[Scale="
3248 << float(fontsSansScale()) / 100
3249 << "," << texmapping << "]{"
3252 os << "\\setsansfont[" << texmapping << "]{"
3255 if (fontsTypewriter() != "default") {
3256 string const mono = parseFontName(fontsTypewriter());
3257 if (fontsTypewriterScale() != 100)
3258 os << "\\setmonofont[Scale="
3259 << float(fontsTypewriterScale()) / 100
3263 os << "\\setmonofont{"
3270 bool const ot1 = (main_font_encoding() == "default" || main_font_encoding() == "OT1");
3271 bool const dryrun = features.runparams().dryrun;
3272 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3273 bool const nomath = (fontsMath() == "default");
3276 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3277 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3281 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3282 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3283 nomath, fontsSansScale());
3285 // MONOSPACED/TYPEWRITER
3286 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3287 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3288 nomath, fontsTypewriterScale());
3291 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3292 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3299 Encoding const & BufferParams::encoding() const
3301 // Main encoding for LaTeX output.
3303 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3304 // As the "flavor" is only known once export started, this
3305 // cannot be handled here. Instead, runparams.encoding is set
3306 // to ASCII in Buffer::makeLaTeXFile (for export)
3307 // and Buffer::writeLaTeXSource (for preview).
3309 return *(encodings.fromLyXName("utf8-plain"));
3310 if (inputenc == "auto" || inputenc == "default")
3311 return *language->encoding();
3312 Encoding const * const enc = encodings.fromLyXName(inputenc);
3315 LYXERR0("Unknown inputenc value `" << inputenc
3316 << "'. Using `auto' instead.");
3317 return *language->encoding();
3321 bool BufferParams::addCiteEngine(string const & engine)
3323 LayoutModuleList::const_iterator it = cite_engine_.begin();
3324 LayoutModuleList::const_iterator en = cite_engine_.end();
3325 for (; it != en; ++it)
3328 cite_engine_.push_back(engine);
3333 bool BufferParams::addCiteEngine(vector<string> const & engine)
3335 vector<string>::const_iterator it = engine.begin();
3336 vector<string>::const_iterator en = engine.end();
3338 for (; it != en; ++it)
3339 if (!addCiteEngine(*it))
3345 string const & BufferParams::defaultBiblioStyle() const
3347 map<string, string> const & bs = documentClass().defaultBiblioStyle();
3348 auto cit = bs.find(theCiteEnginesList.getTypeAsString(citeEngineType()));
3349 if (cit != bs.end())
3352 return empty_string();
3356 bool const & BufferParams::fullAuthorList() const
3358 return documentClass().fullAuthorList();
3362 string BufferParams::getCiteAlias(string const & s) const
3364 vector<string> commands =
3365 documentClass().citeCommands(citeEngineType());
3366 // If it is a real command, don't treat it as an alias
3367 if (find(commands.begin(), commands.end(), s) != commands.end())
3369 map<string,string> aliases = documentClass().citeCommandAliases();
3370 if (aliases.find(s) != aliases.end())
3376 void BufferParams::setCiteEngine(string const & engine)
3379 addCiteEngine(engine);
3383 void BufferParams::setCiteEngine(vector<string> const & engine)
3386 addCiteEngine(engine);
3390 vector<string> BufferParams::citeCommands() const
3392 static CitationStyle const default_style;
3393 vector<string> commands =
3394 documentClass().citeCommands(citeEngineType());
3395 if (commands.empty())
3396 commands.push_back(default_style.name);
3401 vector<CitationStyle> BufferParams::citeStyles() const
3403 static CitationStyle const default_style;
3404 vector<CitationStyle> styles =
3405 documentClass().citeStyles(citeEngineType());
3407 styles.push_back(default_style);
3412 string const BufferParams::bibtexCommand() const
3414 // Return document-specific setting if available
3415 if (bibtex_command != "default")
3416 return bibtex_command;
3418 // If we have "default" in document settings, consult the prefs
3419 // 1. Japanese (uses a specific processor)
3420 if (encoding().package() == Encoding::japanese) {
3421 if (lyxrc.jbibtex_command != "automatic")
3422 // Return the specified program, if "automatic" is not set
3423 return lyxrc.jbibtex_command;
3424 else if (!useBiblatex()) {
3425 // With classic BibTeX, return pbibtex, jbibtex, bibtex
3426 if (lyxrc.jbibtex_alternatives.find("pbibtex") != lyxrc.jbibtex_alternatives.end())
3428 if (lyxrc.jbibtex_alternatives.find("jbibtex") != lyxrc.jbibtex_alternatives.end())
3433 // 2. All other languages
3434 else if (lyxrc.bibtex_command != "automatic")
3435 // Return the specified program, if "automatic" is not set
3436 return lyxrc.bibtex_command;
3438 // 3. Automatic: find the most suitable for the current cite framework
3439 if (useBiblatex()) {
3440 // For Biblatex, we prefer biber (also for Japanese)
3441 // and fall back to bibtex8 and, as last resort, bibtex
3442 if (lyxrc.bibtex_alternatives.find("biber") != lyxrc.bibtex_alternatives.end())
3444 else if (lyxrc.bibtex_alternatives.find("bibtex8") != lyxrc.bibtex_alternatives.end())
3451 bool BufferParams::useBiblatex() const
3453 return theCiteEnginesList[citeEngine().list().front()]
3454 ->getCiteFramework() == "biblatex";
3458 void BufferParams::invalidateConverterCache() const
3460 pimpl_->isExportCacheValid = false;
3461 pimpl_->isViewCacheValid = false;