2 * \file BufferParams.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alfredo Braunstein
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
11 * \author Martin Vermeer
13 * Full author contact details are available in file CREDITS.
18 #include "BufferParams.h"
21 #include "LayoutFile.h"
22 #include "BranchList.h"
24 #include "buffer_funcs.h"
26 #include "CiteEnginesList.h"
29 #include "Converter.h"
32 #include "IndicesList.h"
34 #include "LaTeXFeatures.h"
35 #include "LaTeXFonts.h"
36 #include "ModuleList.h"
40 #include "OutputParams.h"
42 #include "texstream.h"
45 #include "PDFOptions.h"
47 #include "frontends/alert.h"
49 #include "insets/InsetListingsParams.h"
51 #include "support/convert.h"
52 #include "support/debug.h"
53 #include "support/docstream.h"
54 #include "support/FileName.h"
55 #include "support/filetools.h"
56 #include "support/gettext.h"
57 #include "support/Messages.h"
58 #include "support/mutex.h"
59 #include "support/Package.h"
60 #include "support/Translator.h"
61 #include "support/lstrings.h"
67 using namespace lyx::support;
70 static char const * const string_paragraph_separation[] = {
75 static char const * const string_quotes_style[] = {
76 "english", "swedish", "german", "polish", "swiss", "danish", "plain",
77 "british", "swedishg", "french", "frenchin", "russian", "cjk", "cjkangle", ""
81 static char const * const string_papersize[] = {
82 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
83 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
84 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
85 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
86 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
91 static char const * const string_orientation[] = {
92 "portrait", "landscape", ""
96 static char const * const tex_graphics[] = {
97 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
98 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
99 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
100 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
111 // Paragraph separation
112 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
115 ParSepTranslator const init_parseptranslator()
117 ParSepTranslator translator
118 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
119 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
124 ParSepTranslator const & parseptranslator()
126 static ParSepTranslator const translator =
127 init_parseptranslator();
133 typedef Translator<string, InsetQuotesParams::QuoteStyle> QuotesStyleTranslator;
136 QuotesStyleTranslator const init_quotesstyletranslator()
138 QuotesStyleTranslator translator
139 (string_quotes_style[0], InsetQuotesParams::EnglishQuotes);
140 translator.addPair(string_quotes_style[1], InsetQuotesParams::SwedishQuotes);
141 translator.addPair(string_quotes_style[2], InsetQuotesParams::GermanQuotes);
142 translator.addPair(string_quotes_style[3], InsetQuotesParams::PolishQuotes);
143 translator.addPair(string_quotes_style[4], InsetQuotesParams::SwissQuotes);
144 translator.addPair(string_quotes_style[5], InsetQuotesParams::DanishQuotes);
145 translator.addPair(string_quotes_style[6], InsetQuotesParams::PlainQuotes);
146 translator.addPair(string_quotes_style[7], InsetQuotesParams::BritishQuotes);
147 translator.addPair(string_quotes_style[8], InsetQuotesParams::SwedishGQuotes);
148 translator.addPair(string_quotes_style[9], InsetQuotesParams::FrenchQuotes);
149 translator.addPair(string_quotes_style[10], InsetQuotesParams::FrenchINQuotes);
150 translator.addPair(string_quotes_style[11], InsetQuotesParams::RussianQuotes);
151 translator.addPair(string_quotes_style[12], InsetQuotesParams::CJKQuotes);
152 translator.addPair(string_quotes_style[13], InsetQuotesParams::CJKAngleQuotes);
157 QuotesStyleTranslator const & quotesstyletranslator()
159 static QuotesStyleTranslator const translator =
160 init_quotesstyletranslator();
166 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
169 static PaperSizeTranslator initPaperSizeTranslator()
171 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
172 translator.addPair(string_papersize[1], PAPER_CUSTOM);
173 translator.addPair(string_papersize[2], PAPER_USLETTER);
174 translator.addPair(string_papersize[3], PAPER_USLEGAL);
175 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
176 translator.addPair(string_papersize[5], PAPER_A0);
177 translator.addPair(string_papersize[6], PAPER_A1);
178 translator.addPair(string_papersize[7], PAPER_A2);
179 translator.addPair(string_papersize[8], PAPER_A3);
180 translator.addPair(string_papersize[9], PAPER_A4);
181 translator.addPair(string_papersize[10], PAPER_A5);
182 translator.addPair(string_papersize[11], PAPER_A6);
183 translator.addPair(string_papersize[12], PAPER_B0);
184 translator.addPair(string_papersize[13], PAPER_B1);
185 translator.addPair(string_papersize[14], PAPER_B2);
186 translator.addPair(string_papersize[15], PAPER_B3);
187 translator.addPair(string_papersize[16], PAPER_B4);
188 translator.addPair(string_papersize[17], PAPER_B5);
189 translator.addPair(string_papersize[18], PAPER_B6);
190 translator.addPair(string_papersize[19], PAPER_C0);
191 translator.addPair(string_papersize[20], PAPER_C1);
192 translator.addPair(string_papersize[21], PAPER_C2);
193 translator.addPair(string_papersize[22], PAPER_C3);
194 translator.addPair(string_papersize[23], PAPER_C4);
195 translator.addPair(string_papersize[24], PAPER_C5);
196 translator.addPair(string_papersize[25], PAPER_C6);
197 translator.addPair(string_papersize[26], PAPER_JISB0);
198 translator.addPair(string_papersize[27], PAPER_JISB1);
199 translator.addPair(string_papersize[28], PAPER_JISB2);
200 translator.addPair(string_papersize[29], PAPER_JISB3);
201 translator.addPair(string_papersize[30], PAPER_JISB4);
202 translator.addPair(string_papersize[31], PAPER_JISB5);
203 translator.addPair(string_papersize[32], PAPER_JISB6);
208 PaperSizeTranslator const & papersizetranslator()
210 static PaperSizeTranslator const translator =
211 initPaperSizeTranslator();
217 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
220 PaperOrientationTranslator const init_paperorientationtranslator()
222 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
223 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
228 PaperOrientationTranslator const & paperorientationtranslator()
230 static PaperOrientationTranslator const translator =
231 init_paperorientationtranslator();
237 typedef Translator<int, PageSides> SidesTranslator;
240 SidesTranslator const init_sidestranslator()
242 SidesTranslator translator(1, OneSide);
243 translator.addPair(2, TwoSides);
248 SidesTranslator const & sidestranslator()
250 static SidesTranslator const translator = init_sidestranslator();
256 typedef Translator<int, BufferParams::Package> PackageTranslator;
259 PackageTranslator const init_packagetranslator()
261 PackageTranslator translator(0, BufferParams::package_off);
262 translator.addPair(1, BufferParams::package_auto);
263 translator.addPair(2, BufferParams::package_on);
268 PackageTranslator const & packagetranslator()
270 static PackageTranslator const translator =
271 init_packagetranslator();
277 typedef Translator<string, Spacing::Space> SpaceTranslator;
280 SpaceTranslator const init_spacetranslator()
282 SpaceTranslator translator("default", Spacing::Default);
283 translator.addPair("single", Spacing::Single);
284 translator.addPair("onehalf", Spacing::Onehalf);
285 translator.addPair("double", Spacing::Double);
286 translator.addPair("other", Spacing::Other);
291 SpaceTranslator const & spacetranslator()
293 static SpaceTranslator const translator = init_spacetranslator();
298 bool inSystemDir(FileName const & document_dir, string & system_dir)
300 // A document is assumed to be in a system LyX directory (not
301 // necessarily the system directory of the running instance)
302 // if both "configure.py" and "chkconfig.ltx" are found in
303 // either document_dir/../ or document_dir/../../.
304 // If true, the system directory path is returned in system_dir
305 // with a trailing path separator.
307 string const msg = "Checking whether document is in a system dir...";
309 string dir = document_dir.absFileName();
311 for (int i = 0; i < 2; ++i) {
312 dir = addPath(dir, "..");
313 if (!fileSearch(dir, "configure.py").empty() &&
314 !fileSearch(dir, "chkconfig.ltx").empty()) {
315 LYXERR(Debug::FILES, msg << " yes");
316 system_dir = addPath(FileName(dir).realPath(), "");
321 LYXERR(Debug::FILES, msg << " no");
322 system_dir = string();
329 class BufferParams::Impl
334 AuthorList authorlist;
335 BranchList branchlist;
336 Bullet temp_bullets[4];
337 Bullet user_defined_bullets[4];
338 IndicesList indiceslist;
340 /** This is the amount of space used for paragraph_separation "skip",
341 * and for detached paragraphs in "indented" documents.
345 PDFOptions pdfoptions;
346 LayoutFileIndex baseClass_;
347 FormatList exportableFormatList;
348 FormatList viewableFormatList;
349 bool isViewCacheValid;
350 bool isExportCacheValid;
354 BufferParams::Impl::Impl()
355 : defskip(VSpace::MEDSKIP), baseClass_(string("")),
356 isViewCacheValid(false), isExportCacheValid(false)
358 // set initial author
360 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
365 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
368 return new BufferParams::Impl(*ptr);
372 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
378 BufferParams::BufferParams()
381 setBaseClass(defaultBaseclass());
382 cite_engine_.push_back("basic");
383 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
385 paragraph_separation = ParagraphIndentSeparation;
386 quotes_style = InsetQuotesParams::EnglishQuotes;
387 dynamic_quotes = false;
388 fontsize = "default";
391 papersize = PAPER_DEFAULT;
392 orientation = ORIENTATION_PORTRAIT;
393 use_geometry = false;
394 biblio_style = "plain";
395 use_bibtopic = false;
397 save_transient_properties = true;
398 track_changes = false;
399 output_changes = false;
400 use_default_options = true;
401 maintain_unincluded_children = false;
404 language = default_language;
406 fonts_roman[0] = "default";
407 fonts_roman[1] = "default";
408 fonts_sans[0] = "default";
409 fonts_sans[1] = "default";
410 fonts_typewriter[0] = "default";
411 fonts_typewriter[1] = "default";
412 fonts_math[0] = "auto";
413 fonts_math[1] = "auto";
414 fonts_default_family = "default";
415 useNonTeXFonts = false;
416 use_microtype = false;
417 fonts_expert_sc = false;
418 fonts_old_figures = false;
419 fonts_sans_scale[0] = 100;
420 fonts_sans_scale[1] = 100;
421 fonts_typewriter_scale[0] = 100;
422 fonts_typewriter_scale[1] = 100;
424 lang_package = "default";
425 graphics_driver = "default";
426 default_output_format = "default";
427 bibtex_command = "default";
428 index_command = "default";
431 listings_params = string();
432 pagestyle = "default";
433 suppress_date = false;
434 justification = true;
435 // no color is the default (white)
436 backgroundcolor = lyx::rgbFromHexName("#ffffff");
437 isbackgroundcolor = false;
438 // no color is the default (black)
439 fontcolor = lyx::rgbFromHexName("#000000");
441 // light gray is the default font color for greyed-out notes
442 notefontcolor = lyx::rgbFromHexName("#cccccc");
443 boxbgcolor = lyx::rgbFromHexName("#ff0000");
444 compressed = lyxrc.save_compressed;
445 for (int iter = 0; iter < 4; ++iter) {
446 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
447 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
450 indiceslist().addDefault(B_("Index"));
451 html_be_strict = false;
452 html_math_output = MathML;
453 html_math_img_scale = 1.0;
454 html_css_as_file = false;
455 display_pixel_ratio = 1.0;
460 // map current author
461 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
465 docstring BufferParams::B_(string const & l10n) const
467 LASSERT(language, return from_utf8(l10n));
468 return getMessages(language->code()).get(l10n);
472 BufferParams::Package BufferParams::use_package(std::string const & p) const
474 PackageMap::const_iterator it = use_packages.find(p);
475 if (it == use_packages.end())
481 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
487 map<string, string> const & BufferParams::auto_packages()
489 static map<string, string> packages;
490 if (packages.empty()) {
491 // We could have a race condition here that two threads
492 // discover an empty map at the same time and want to fill
493 // it, but that is no problem, since the same contents is
494 // filled in twice then. Having the locker inside the
495 // packages.empty() condition has the advantage that we
496 // don't need the mutex overhead for simple reading.
498 Mutex::Locker locker(&mutex);
499 // adding a package here implies a file format change!
500 packages["amsmath"] =
501 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
502 packages["amssymb"] =
503 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
505 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
507 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
508 packages["mathdots"] =
509 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
510 packages["mathtools"] =
511 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
513 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
514 packages["stackrel"] =
515 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
516 packages["stmaryrd"] =
517 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");
518 packages["undertilde"] =
519 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
525 AuthorList & BufferParams::authors()
527 return pimpl_->authorlist;
531 AuthorList const & BufferParams::authors() const
533 return pimpl_->authorlist;
537 void BufferParams::addAuthor(Author a)
539 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
543 BranchList & BufferParams::branchlist()
545 return pimpl_->branchlist;
549 BranchList const & BufferParams::branchlist() const
551 return pimpl_->branchlist;
555 IndicesList & BufferParams::indiceslist()
557 return pimpl_->indiceslist;
561 IndicesList const & BufferParams::indiceslist() const
563 return pimpl_->indiceslist;
567 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
569 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
570 return pimpl_->temp_bullets[index];
574 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
576 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
577 return pimpl_->temp_bullets[index];
581 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
583 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
584 return pimpl_->user_defined_bullets[index];
588 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
590 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
591 return pimpl_->user_defined_bullets[index];
595 Spacing & BufferParams::spacing()
597 return pimpl_->spacing;
601 Spacing const & BufferParams::spacing() const
603 return pimpl_->spacing;
607 PDFOptions & BufferParams::pdfoptions()
609 return pimpl_->pdfoptions;
613 PDFOptions const & BufferParams::pdfoptions() const
615 return pimpl_->pdfoptions;
619 HSpace const & BufferParams::getIndentation() const
621 return pimpl_->indentation;
625 void BufferParams::setIndentation(HSpace const & indent)
627 pimpl_->indentation = indent;
631 VSpace const & BufferParams::getDefSkip() const
633 return pimpl_->defskip;
637 void BufferParams::setDefSkip(VSpace const & vs)
639 // DEFSKIP will cause an infinite loop
640 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
641 pimpl_->defskip = vs;
645 string BufferParams::readToken(Lexer & lex, string const & token,
646 FileName const & filepath)
650 if (token == "\\textclass") {
652 string const classname = lex.getString();
653 // if there exists a local layout file, ignore the system one
654 // NOTE: in this case, the textclass (.cls file) is assumed to
657 LayoutFileList & bcl = LayoutFileList::get();
658 if (!filepath.empty()) {
659 // If classname is an absolute path, the document is
660 // using a local layout file which could not be accessed
661 // by a relative path. In this case the path is correct
662 // even if the document was moved to a different
663 // location. However, we will have a problem if the
664 // document was generated on a different platform.
665 bool isabsolute = FileName::isAbsolute(classname);
666 string const classpath = onlyPath(classname);
667 string const path = isabsolute ? classpath
668 : FileName(addPath(filepath.absFileName(),
669 classpath)).realPath();
670 string const oldpath = isabsolute ? string()
671 : FileName(addPath(origin, classpath)).realPath();
672 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
674 // that returns non-empty if a "local" layout file is found.
676 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
677 from_utf8(filepath.absFileName())));
680 setBaseClass(onlyFileName(tcp));
682 setBaseClass(onlyFileName(classname));
683 // We assume that a tex class exists for local or unknown
684 // layouts so this warning, will only be given for system layouts.
685 if (!baseClass()->isTeXClassAvailable()) {
686 docstring const desc =
687 translateIfPossible(from_utf8(baseClass()->description()));
688 docstring const prereqs =
689 from_utf8(baseClass()->prerequisites());
690 docstring const msg =
691 bformat(_("The selected document class\n"
693 "requires external files that are not available.\n"
694 "The document class can still be used, but the\n"
695 "document cannot be compiled until the following\n"
696 "prerequisites are installed:\n"
698 "See section 3.1.2.2 (Class Availability) of the\n"
699 "User's Guide for more information."), desc, prereqs);
700 frontend::Alert::warning(_("Document class not available"),
703 } else if (token == "\\save_transient_properties") {
704 lex >> save_transient_properties;
705 } else if (token == "\\origin") {
707 origin = lex.getString();
708 string const sysdirprefix = "/systemlyxdir/";
709 if (prefixIs(origin, sysdirprefix)) {
711 if (inSystemDir(filepath, docsys))
712 origin.replace(0, sysdirprefix.length() - 1, docsys);
714 origin.replace(0, sysdirprefix.length() - 1,
715 package().system_support().absFileName());
717 } else if (token == "\\begin_preamble") {
719 } else if (token == "\\begin_local_layout") {
720 readLocalLayout(lex, false);
721 } else if (token == "\\begin_forced_local_layout") {
722 readLocalLayout(lex, true);
723 } else if (token == "\\begin_modules") {
725 } else if (token == "\\begin_removed_modules") {
726 readRemovedModules(lex);
727 } else if (token == "\\begin_includeonly") {
728 readIncludeonly(lex);
729 } else if (token == "\\maintain_unincluded_children") {
730 lex >> maintain_unincluded_children;
731 } else if (token == "\\options") {
733 options = lex.getString();
734 } else if (token == "\\use_default_options") {
735 lex >> use_default_options;
736 } else if (token == "\\master") {
738 master = lex.getString();
739 if (!filepath.empty() && FileName::isAbsolute(origin)) {
740 bool const isabs = FileName::isAbsolute(master);
741 FileName const abspath(isabs ? master : origin + master);
742 bool const moved = filepath != FileName(origin);
743 if (moved && abspath.exists()) {
744 docstring const path = isabs
746 : from_utf8(abspath.realPath());
747 docstring const refpath =
748 from_utf8(filepath.absFileName());
749 master = to_utf8(makeRelPath(path, refpath));
752 } else if (token == "\\suppress_date") {
753 lex >> suppress_date;
754 } else if (token == "\\justification") {
755 lex >> justification;
756 } else if (token == "\\language") {
758 } else if (token == "\\language_package") {
760 lang_package = lex.getString();
761 } else if (token == "\\inputencoding") {
763 } else if (token == "\\graphics") {
764 readGraphicsDriver(lex);
765 } else if (token == "\\default_output_format") {
766 lex >> default_output_format;
767 } else if (token == "\\bibtex_command") {
769 bibtex_command = lex.getString();
770 } else if (token == "\\index_command") {
772 index_command = lex.getString();
773 } else if (token == "\\fontencoding") {
775 fontenc = lex.getString();
776 } else if (token == "\\font_roman") {
777 lex >> fonts_roman[0];
778 lex >> fonts_roman[1];
779 } else if (token == "\\font_sans") {
780 lex >> fonts_sans[0];
781 lex >> fonts_sans[1];
782 } else if (token == "\\font_typewriter") {
783 lex >> fonts_typewriter[0];
784 lex >> fonts_typewriter[1];
785 } else if (token == "\\font_math") {
786 lex >> fonts_math[0];
787 lex >> fonts_math[1];
788 } else if (token == "\\font_default_family") {
789 lex >> fonts_default_family;
790 } else if (token == "\\use_non_tex_fonts") {
791 lex >> useNonTeXFonts;
792 } else if (token == "\\font_sc") {
793 lex >> fonts_expert_sc;
794 } else if (token == "\\font_osf") {
795 lex >> fonts_old_figures;
796 } else if (token == "\\font_sf_scale") {
797 lex >> fonts_sans_scale[0];
798 lex >> fonts_sans_scale[1];
799 } else if (token == "\\font_tt_scale") {
800 lex >> fonts_typewriter_scale[0];
801 lex >> fonts_typewriter_scale[1];
802 } else if (token == "\\font_cjk") {
804 } else if (token == "\\use_microtype") {
805 lex >> use_microtype;
806 } else if (token == "\\paragraph_separation") {
809 paragraph_separation = parseptranslator().find(parsep);
810 } else if (token == "\\paragraph_indentation") {
812 string indentation = lex.getString();
813 pimpl_->indentation = HSpace(indentation);
814 } else if (token == "\\defskip") {
816 string const defskip = lex.getString();
817 pimpl_->defskip = VSpace(defskip);
818 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
820 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
821 } else if (token == "\\quotes_style") {
824 quotes_style = quotesstyletranslator().find(qstyle);
825 } else if (token == "\\dynamic_quotes") {
826 lex >> dynamic_quotes;
827 } else if (token == "\\papersize") {
830 papersize = papersizetranslator().find(ppsize);
831 } else if (token == "\\use_geometry") {
833 } else if (token == "\\use_package") {
838 use_package(package, packagetranslator().find(use));
839 } else if (token == "\\cite_engine") {
841 vector<string> engine = getVectorFromString(lex.getString());
842 setCiteEngine(engine);
843 } else if (token == "\\cite_engine_type") {
846 cite_engine_type_ = theCiteEnginesList.getType(engine_type);
847 } else if (token == "\\biblio_style") {
849 biblio_style = lex.getString();
850 } else if (token == "\\use_bibtopic") {
852 } else if (token == "\\use_indices") {
854 } else if (token == "\\tracking_changes") {
855 lex >> track_changes;
856 } else if (token == "\\output_changes") {
857 lex >> output_changes;
858 } else if (token == "\\branch") {
860 docstring branch = lex.getDocString();
861 branchlist().add(branch);
864 string const tok = lex.getString();
865 if (tok == "\\end_branch")
867 Branch * branch_ptr = branchlist().find(branch);
868 if (tok == "\\selected") {
871 branch_ptr->setSelected(lex.getInteger());
873 if (tok == "\\filename_suffix") {
876 branch_ptr->setFileNameSuffix(lex.getInteger());
878 if (tok == "\\color") {
880 string color = lex.getString();
882 branch_ptr->setColor(color);
883 // Update also the Color table:
885 color = lcolor.getX11Name(Color_background);
887 lcolor.setColor(to_utf8(branch), color);
890 } else if (token == "\\index") {
892 docstring index = lex.getDocString();
894 indiceslist().add(index);
897 string const tok = lex.getString();
898 if (tok == "\\end_index")
900 Index * index_ptr = indiceslist().find(index);
901 if (tok == "\\shortcut") {
903 shortcut = lex.getDocString();
905 index_ptr->setShortcut(shortcut);
907 if (tok == "\\color") {
909 string color = lex.getString();
911 index_ptr->setColor(color);
912 // Update also the Color table:
914 color = lcolor.getX11Name(Color_background);
916 if (!shortcut.empty())
917 lcolor.setColor(to_utf8(shortcut), color);
920 } else if (token == "\\author") {
922 istringstream ss(lex.getString());
926 } else if (token == "\\paperorientation") {
929 orientation = paperorientationtranslator().find(orient);
930 } else if (token == "\\backgroundcolor") {
932 backgroundcolor = lyx::rgbFromHexName(lex.getString());
933 isbackgroundcolor = true;
934 } else if (token == "\\fontcolor") {
936 fontcolor = lyx::rgbFromHexName(lex.getString());
938 } else if (token == "\\notefontcolor") {
940 string color = lex.getString();
941 notefontcolor = lyx::rgbFromHexName(color);
942 lcolor.setColor("notefontcolor", color);
943 } else if (token == "\\boxbgcolor") {
945 string color = lex.getString();
946 boxbgcolor = lyx::rgbFromHexName(color);
947 lcolor.setColor("boxbgcolor", color);
948 } else if (token == "\\paperwidth") {
950 } else if (token == "\\paperheight") {
952 } else if (token == "\\leftmargin") {
954 } else if (token == "\\topmargin") {
956 } else if (token == "\\rightmargin") {
958 } else if (token == "\\bottommargin") {
960 } else if (token == "\\headheight") {
962 } else if (token == "\\headsep") {
964 } else if (token == "\\footskip") {
966 } else if (token == "\\columnsep") {
968 } else if (token == "\\paperfontsize") {
970 } else if (token == "\\papercolumns") {
972 } else if (token == "\\listings_params") {
975 listings_params = InsetListingsParams(par).params();
976 } else if (token == "\\papersides") {
979 sides = sidestranslator().find(psides);
980 } else if (token == "\\paperpagestyle") {
982 } else if (token == "\\bullet") {
984 } else if (token == "\\bulletLaTeX") {
985 readBulletsLaTeX(lex);
986 } else if (token == "\\secnumdepth") {
988 } else if (token == "\\tocdepth") {
990 } else if (token == "\\spacing") {
994 if (nspacing == "other") {
997 spacing().set(spacetranslator().find(nspacing), tmp_val);
998 } else if (token == "\\float_placement") {
999 lex >> float_placement;
1001 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
1002 string toktmp = pdfoptions().readToken(lex, token);
1003 if (!toktmp.empty()) {
1004 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
1008 } else if (token == "\\html_math_output") {
1011 html_math_output = static_cast<MathOutput>(temp);
1012 } else if (token == "\\html_be_strict") {
1013 lex >> html_be_strict;
1014 } else if (token == "\\html_css_as_file") {
1015 lex >> html_css_as_file;
1016 } else if (token == "\\html_math_img_scale") {
1017 lex >> html_math_img_scale;
1018 } else if (token == "\\html_latex_start") {
1020 html_latex_start = lex.getString();
1021 } else if (token == "\\html_latex_end") {
1023 html_latex_end = lex.getString();
1024 } else if (token == "\\output_sync") {
1026 } else if (token == "\\output_sync_macro") {
1027 lex >> output_sync_macro;
1028 } else if (token == "\\use_refstyle") {
1029 lex >> use_refstyle;
1031 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1041 // Quote argument if it contains spaces
1042 string quoteIfNeeded(string const & str) {
1043 if (contains(str, ' '))
1044 return "\"" + str + "\"";
1050 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1052 // The top of the file is written by the buffer.
1053 // Prints out the buffer info into the .lyx file given by file
1055 os << "\\save_transient_properties "
1056 << convert<string>(save_transient_properties) << '\n';
1058 // the document directory (must end with a path separator)
1059 // realPath() is used to resolve symlinks, while addPath(..., "")
1060 // ensures a trailing path separator.
1062 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1063 string const sysdir = inSystemDir(FileName(filepath), docsys) ? docsys
1064 : addPath(package().system_support().realPath(), "");
1065 string const relpath =
1066 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1067 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1068 filepath = addPath("/systemlyxdir", relpath);
1069 else if (!save_transient_properties || !lyxrc.save_origin)
1070 filepath = "unavailable";
1071 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1074 os << "\\textclass "
1075 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1076 baseClass()->name()), "layout"))
1079 // then the preamble
1080 if (!preamble.empty()) {
1081 // remove '\n' from the end of preamble
1082 docstring const tmppreamble = rtrim(preamble, "\n");
1083 os << "\\begin_preamble\n"
1084 << to_utf8(tmppreamble)
1085 << "\n\\end_preamble\n";
1089 if (!options.empty()) {
1090 os << "\\options " << options << '\n';
1093 // use the class options defined in the layout?
1094 os << "\\use_default_options "
1095 << convert<string>(use_default_options) << "\n";
1097 // the master document
1098 if (!master.empty()) {
1099 os << "\\master " << master << '\n';
1103 if (!removed_modules_.empty()) {
1104 os << "\\begin_removed_modules" << '\n';
1105 list<string>::const_iterator it = removed_modules_.begin();
1106 list<string>::const_iterator en = removed_modules_.end();
1107 for (; it != en; ++it)
1109 os << "\\end_removed_modules" << '\n';
1113 if (!layout_modules_.empty()) {
1114 os << "\\begin_modules" << '\n';
1115 LayoutModuleList::const_iterator it = layout_modules_.begin();
1116 LayoutModuleList::const_iterator en = layout_modules_.end();
1117 for (; it != en; ++it)
1119 os << "\\end_modules" << '\n';
1123 if (!included_children_.empty()) {
1124 os << "\\begin_includeonly" << '\n';
1125 list<string>::const_iterator it = included_children_.begin();
1126 list<string>::const_iterator en = included_children_.end();
1127 for (; it != en; ++it)
1129 os << "\\end_includeonly" << '\n';
1131 os << "\\maintain_unincluded_children "
1132 << convert<string>(maintain_unincluded_children) << '\n';
1134 // local layout information
1135 docstring const local_layout = getLocalLayout(false);
1136 if (!local_layout.empty()) {
1137 // remove '\n' from the end
1138 docstring const tmplocal = rtrim(local_layout, "\n");
1139 os << "\\begin_local_layout\n"
1140 << to_utf8(tmplocal)
1141 << "\n\\end_local_layout\n";
1143 docstring const forced_local_layout = getLocalLayout(true);
1144 if (!forced_local_layout.empty()) {
1145 // remove '\n' from the end
1146 docstring const tmplocal = rtrim(forced_local_layout, "\n");
1147 os << "\\begin_forced_local_layout\n"
1148 << to_utf8(tmplocal)
1149 << "\n\\end_forced_local_layout\n";
1152 // then the text parameters
1153 if (language != ignore_language)
1154 os << "\\language " << language->lang() << '\n';
1155 os << "\\language_package " << lang_package
1156 << "\n\\inputencoding " << inputenc
1157 << "\n\\fontencoding " << fontenc
1158 << "\n\\font_roman \"" << fonts_roman[0]
1159 << "\" \"" << fonts_roman[1] << '"'
1160 << "\n\\font_sans \"" << fonts_sans[0]
1161 << "\" \"" << fonts_sans[1] << '"'
1162 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1163 << "\" \"" << fonts_typewriter[1] << '"'
1164 << "\n\\font_math \"" << fonts_math[0]
1165 << "\" \"" << fonts_math[1] << '"'
1166 << "\n\\font_default_family " << fonts_default_family
1167 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1168 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1169 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1170 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1171 << ' ' << fonts_sans_scale[1]
1172 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1173 << ' ' << fonts_typewriter_scale[1]
1175 if (!fonts_cjk.empty()) {
1176 os << "\\font_cjk " << fonts_cjk << '\n';
1178 os << "\\use_microtype " << convert<string>(use_microtype) << '\n';
1179 os << "\\graphics " << graphics_driver << '\n';
1180 os << "\\default_output_format " << default_output_format << '\n';
1181 os << "\\output_sync " << output_sync << '\n';
1182 if (!output_sync_macro.empty())
1183 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1184 os << "\\bibtex_command " << bibtex_command << '\n';
1185 os << "\\index_command " << index_command << '\n';
1187 if (!float_placement.empty()) {
1188 os << "\\float_placement " << float_placement << '\n';
1190 os << "\\paperfontsize " << fontsize << '\n';
1192 spacing().writeFile(os);
1193 pdfoptions().writeFile(os);
1195 os << "\\papersize " << string_papersize[papersize]
1196 << "\n\\use_geometry " << convert<string>(use_geometry);
1197 map<string, string> const & packages = auto_packages();
1198 for (map<string, string>::const_iterator it = packages.begin();
1199 it != packages.end(); ++it)
1200 os << "\n\\use_package " << it->first << ' '
1201 << use_package(it->first);
1203 os << "\n\\cite_engine ";
1205 if (!cite_engine_.empty()) {
1206 LayoutModuleList::const_iterator be = cite_engine_.begin();
1207 LayoutModuleList::const_iterator en = cite_engine_.end();
1208 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1217 os << "\n\\cite_engine_type " << theCiteEnginesList.getTypeAsString(cite_engine_type_)
1218 << "\n\\biblio_style " << biblio_style
1219 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1220 << "\n\\use_indices " << convert<string>(use_indices)
1221 << "\n\\paperorientation " << string_orientation[orientation]
1222 << "\n\\suppress_date " << convert<string>(suppress_date)
1223 << "\n\\justification " << convert<string>(justification)
1224 << "\n\\use_refstyle " << use_refstyle
1226 if (isbackgroundcolor == true)
1227 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1228 if (isfontcolor == true)
1229 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1230 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1231 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1232 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1233 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1235 BranchList::const_iterator it = branchlist().begin();
1236 BranchList::const_iterator end = branchlist().end();
1237 for (; it != end; ++it) {
1238 os << "\\branch " << to_utf8(it->branch())
1239 << "\n\\selected " << it->isSelected()
1240 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1241 << "\n\\color " << lyx::X11hexname(it->color())
1246 IndicesList::const_iterator iit = indiceslist().begin();
1247 IndicesList::const_iterator iend = indiceslist().end();
1248 for (; iit != iend; ++iit) {
1249 os << "\\index " << to_utf8(iit->index())
1250 << "\n\\shortcut " << to_utf8(iit->shortcut())
1251 << "\n\\color " << lyx::X11hexname(iit->color())
1256 if (!paperwidth.empty())
1257 os << "\\paperwidth "
1258 << VSpace(paperwidth).asLyXCommand() << '\n';
1259 if (!paperheight.empty())
1260 os << "\\paperheight "
1261 << VSpace(paperheight).asLyXCommand() << '\n';
1262 if (!leftmargin.empty())
1263 os << "\\leftmargin "
1264 << VSpace(leftmargin).asLyXCommand() << '\n';
1265 if (!topmargin.empty())
1266 os << "\\topmargin "
1267 << VSpace(topmargin).asLyXCommand() << '\n';
1268 if (!rightmargin.empty())
1269 os << "\\rightmargin "
1270 << VSpace(rightmargin).asLyXCommand() << '\n';
1271 if (!bottommargin.empty())
1272 os << "\\bottommargin "
1273 << VSpace(bottommargin).asLyXCommand() << '\n';
1274 if (!headheight.empty())
1275 os << "\\headheight "
1276 << VSpace(headheight).asLyXCommand() << '\n';
1277 if (!headsep.empty())
1279 << VSpace(headsep).asLyXCommand() << '\n';
1280 if (!footskip.empty())
1282 << VSpace(footskip).asLyXCommand() << '\n';
1283 if (!columnsep.empty())
1284 os << "\\columnsep "
1285 << VSpace(columnsep).asLyXCommand() << '\n';
1286 os << "\\secnumdepth " << secnumdepth
1287 << "\n\\tocdepth " << tocdepth
1288 << "\n\\paragraph_separation "
1289 << string_paragraph_separation[paragraph_separation];
1290 if (!paragraph_separation)
1291 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1293 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1294 os << "\n\\quotes_style "
1295 << string_quotes_style[quotes_style]
1296 << "\n\\dynamic_quotes " << dynamic_quotes
1297 << "\n\\papercolumns " << columns
1298 << "\n\\papersides " << sides
1299 << "\n\\paperpagestyle " << pagestyle << '\n';
1300 if (!listings_params.empty())
1301 os << "\\listings_params \"" <<
1302 InsetListingsParams(listings_params).encodedString() << "\"\n";
1303 for (int i = 0; i < 4; ++i) {
1304 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1305 if (user_defined_bullet(i).getFont() != -1) {
1306 os << "\\bullet " << i << " "
1307 << user_defined_bullet(i).getFont() << " "
1308 << user_defined_bullet(i).getCharacter() << " "
1309 << user_defined_bullet(i).getSize() << "\n";
1313 os << "\\bulletLaTeX " << i << " \""
1314 << lyx::to_ascii(user_defined_bullet(i).getText())
1320 os << "\\tracking_changes "
1321 << (save_transient_properties ? convert<string>(track_changes) : "false")
1324 os << "\\output_changes "
1325 << (save_transient_properties ? convert<string>(output_changes) : "false")
1328 os << "\\html_math_output " << html_math_output << '\n'
1329 << "\\html_css_as_file " << html_css_as_file << '\n'
1330 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1332 if (html_math_img_scale != 1.0)
1333 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1334 if (!html_latex_start.empty())
1335 os << "\\html_latex_start " << html_latex_start << '\n';
1336 if (!html_latex_end.empty())
1337 os << "\\html_latex_end " << html_latex_end << '\n';
1339 os << pimpl_->authorlist;
1343 void BufferParams::validate(LaTeXFeatures & features) const
1345 features.require(documentClass().requires());
1347 if (columns > 1 && language->rightToLeft())
1348 features.require("rtloutputdblcol");
1350 if (output_changes) {
1351 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1352 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1353 LaTeXFeatures::isAvailable("xcolor");
1355 switch (features.runparams().flavor) {
1356 case OutputParams::LATEX:
1357 case OutputParams::DVILUATEX:
1359 features.require("ct-dvipost");
1360 features.require("dvipost");
1361 } else if (xcolorulem) {
1362 features.require("ct-xcolor-ulem");
1363 features.require("ulem");
1364 features.require("xcolor");
1366 features.require("ct-none");
1369 case OutputParams::LUATEX:
1370 case OutputParams::PDFLATEX:
1371 case OutputParams::XETEX:
1373 features.require("ct-xcolor-ulem");
1374 features.require("ulem");
1375 features.require("xcolor");
1376 // improves color handling in PDF output
1377 features.require("pdfcolmk");
1379 features.require("ct-none");
1387 // Floats with 'Here definitely' as default setting.
1388 if (float_placement.find('H') != string::npos)
1389 features.require("float");
1391 for (PackageMap::const_iterator it = use_packages.begin();
1392 it != use_packages.end(); ++it) {
1393 if (it->first == "amsmath") {
1394 // AMS Style is at document level
1395 if (it->second == package_on ||
1396 features.isProvided("amsmath"))
1397 features.require(it->first);
1398 } else if (it->second == package_on)
1399 features.require(it->first);
1402 // Document-level line spacing
1403 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1404 features.require("setspace");
1406 // the bullet shapes are buffer level not paragraph level
1407 // so they are tested here
1408 for (int i = 0; i < 4; ++i) {
1409 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1411 int const font = user_defined_bullet(i).getFont();
1413 int const c = user_defined_bullet(i).getCharacter();
1419 features.require("latexsym");
1421 } else if (font == 1) {
1422 features.require("amssymb");
1423 } else if (font >= 2 && font <= 5) {
1424 features.require("pifont");
1428 if (pdfoptions().use_hyperref) {
1429 features.require("hyperref");
1430 // due to interferences with babel and hyperref, the color package has to
1431 // be loaded after hyperref when hyperref is used with the colorlinks
1432 // option, see http://www.lyx.org/trac/ticket/5291
1433 if (pdfoptions().colorlinks)
1434 features.require("color");
1436 if (!listings_params.empty()) {
1437 // do not test validity because listings_params is
1438 // supposed to be valid
1440 InsetListingsParams(listings_params).separatedParams(true);
1441 // we can't support all packages, but we should load the color package
1442 if (par.find("\\color", 0) != string::npos)
1443 features.require("color");
1446 // some languages are only available via polyglossia
1447 if (features.hasPolyglossiaExclusiveLanguages())
1448 features.require("polyglossia");
1450 if (useNonTeXFonts && fontsMath() != "auto")
1451 features.require("unicode-math");
1454 features.require("microtype");
1456 if (!language->requires().empty())
1457 features.require(language->requires());
1461 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1462 FileName const & filepath) const
1464 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1465 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1466 // \RequirePackage to do so, rather than the normal \usepackage
1467 // Do not try to load any other package before the document class, unless you
1468 // have a thorough understanding of the LATEX internals and know exactly what you
1470 if (features.mustProvide("fix-cm"))
1471 os << "\\RequirePackage{fix-cm}\n";
1472 // Likewise for fixltx2e. If other packages conflict with this policy,
1473 // treat it as a package bug (and report it!)
1474 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1475 if (features.mustProvide("fixltx2e"))
1476 os << "\\RequirePackage{fixltx2e}\n";
1478 os << "\\documentclass";
1480 DocumentClass const & tclass = documentClass();
1482 ostringstream clsoptions; // the document class options.
1484 if (tokenPos(tclass.opt_fontsize(),
1485 '|', fontsize) >= 0) {
1486 // only write if existing in list (and not default)
1487 clsoptions << fontsize << "pt,";
1490 // all paper sizes except of A4, A5, B5 and the US sizes need the
1492 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1493 && papersize != PAPER_USLETTER
1494 && papersize != PAPER_USLEGAL
1495 && papersize != PAPER_USEXECUTIVE
1496 && papersize != PAPER_A4
1497 && papersize != PAPER_A5
1498 && papersize != PAPER_B5;
1500 if (!use_geometry) {
1501 switch (papersize) {
1503 clsoptions << "a4paper,";
1505 case PAPER_USLETTER:
1506 clsoptions << "letterpaper,";
1509 clsoptions << "a5paper,";
1512 clsoptions << "b5paper,";
1514 case PAPER_USEXECUTIVE:
1515 clsoptions << "executivepaper,";
1518 clsoptions << "legalpaper,";
1552 if (sides != tclass.sides()) {
1555 clsoptions << "oneside,";
1558 clsoptions << "twoside,";
1564 if (columns != tclass.columns()) {
1566 clsoptions << "twocolumn,";
1568 clsoptions << "onecolumn,";
1572 && orientation == ORIENTATION_LANDSCAPE)
1573 clsoptions << "landscape,";
1575 // language should be a parameter to \documentclass
1576 if (language->babel() == "hebrew"
1577 && default_language->babel() != "hebrew")
1578 // This seems necessary
1579 features.useLanguage(default_language);
1581 ostringstream language_options;
1582 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1583 bool const use_polyglossia = features.usePolyglossia();
1584 bool const global = lyxrc.language_global_options;
1585 if (use_babel || (use_polyglossia && global)) {
1586 language_options << features.getBabelLanguages();
1587 if (!language->babel().empty()) {
1588 if (!language_options.str().empty())
1589 language_options << ',';
1590 language_options << language->babel();
1592 if (global && !features.needBabelLangOptions()
1593 && !language_options.str().empty())
1594 clsoptions << language_options.str() << ',';
1597 // the predefined options from the layout
1598 if (use_default_options && !tclass.options().empty())
1599 clsoptions << tclass.options() << ',';
1601 // the user-defined options
1602 if (!options.empty()) {
1603 clsoptions << options << ',';
1606 string strOptions(clsoptions.str());
1607 if (!strOptions.empty()) {
1608 strOptions = rtrim(strOptions, ",");
1610 os << '[' << from_utf8(strOptions) << ']';
1613 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1614 // end of \documentclass defs
1616 // if we use fontspec or newtxmath, we have to load the AMS packages here
1617 string const ams = features.loadAMSPackages();
1618 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1619 bool const use_newtxmath =
1620 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1621 ot1, false, false) == "newtxmath";
1622 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1623 os << from_ascii(ams);
1625 if (useNonTeXFonts) {
1626 if (!features.isProvided("fontspec"))
1627 os << "\\usepackage{fontspec}\n";
1628 if (features.mustProvide("unicode-math")
1629 && features.isAvailable("unicode-math"))
1630 os << "\\usepackage{unicode-math}\n";
1633 // font selection must be done before loading fontenc.sty
1634 string const fonts = loadFonts(features);
1636 os << from_utf8(fonts);
1638 if (fonts_default_family != "default")
1639 os << "\\renewcommand{\\familydefault}{\\"
1640 << from_ascii(fonts_default_family) << "}\n";
1642 // set font encoding
1643 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1644 if (!useNonTeXFonts && !features.isProvided("fontenc")
1645 && font_encoding() != "default") {
1646 // get main font encodings
1647 vector<string> fontencs = font_encodings();
1648 // get font encodings of secondary languages
1649 features.getFontEncodings(fontencs);
1650 if (!fontencs.empty()) {
1651 os << "\\usepackage["
1652 << from_ascii(getStringFromVector(fontencs))
1657 // handle inputenc etc.
1658 writeEncodingPreamble(os, features);
1661 if (!features.runparams().includeall && !included_children_.empty()) {
1662 os << "\\includeonly{";
1663 list<string>::const_iterator it = included_children_.begin();
1664 list<string>::const_iterator en = included_children_.end();
1666 for (; it != en; ++it) {
1667 string incfile = *it;
1668 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1669 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1671 if (!features.runparams().nice)
1673 // \includeonly doesn't want an extension
1674 incfile = changeExtension(incfile, string());
1675 incfile = support::latex_path(incfile);
1676 if (!incfile.empty()) {
1679 os << from_utf8(incfile);
1686 if (!features.isProvided("geometry")
1687 && (use_geometry || nonstandard_papersize)) {
1688 odocstringstream ods;
1689 if (!getGraphicsDriver("geometry").empty())
1690 ods << getGraphicsDriver("geometry");
1691 if (orientation == ORIENTATION_LANDSCAPE)
1692 ods << ",landscape";
1693 switch (papersize) {
1695 if (!paperwidth.empty())
1696 ods << ",paperwidth="
1697 << from_ascii(paperwidth);
1698 if (!paperheight.empty())
1699 ods << ",paperheight="
1700 << from_ascii(paperheight);
1702 case PAPER_USLETTER:
1703 ods << ",letterpaper";
1706 ods << ",legalpaper";
1708 case PAPER_USEXECUTIVE:
1709 ods << ",executivepaper";
1798 docstring const g_options = trim(ods.str(), ",");
1799 os << "\\usepackage";
1800 if (!g_options.empty())
1801 os << '[' << g_options << ']';
1802 os << "{geometry}\n";
1803 // output this only if use_geometry is true
1805 os << "\\geometry{verbose";
1806 if (!topmargin.empty())
1807 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1808 if (!bottommargin.empty())
1809 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1810 if (!leftmargin.empty())
1811 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1812 if (!rightmargin.empty())
1813 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1814 if (!headheight.empty())
1815 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1816 if (!headsep.empty())
1817 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1818 if (!footskip.empty())
1819 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1820 if (!columnsep.empty())
1821 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1824 } else if (orientation == ORIENTATION_LANDSCAPE
1825 || papersize != PAPER_DEFAULT) {
1826 features.require("papersize");
1829 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1830 if (pagestyle == "fancy")
1831 os << "\\usepackage{fancyhdr}\n";
1832 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1835 // only output when the background color is not default
1836 if (isbackgroundcolor == true) {
1837 // only require color here, the background color will be defined
1838 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1840 features.require("color");
1841 features.require("pagecolor");
1844 // only output when the font color is not default
1845 if (isfontcolor == true) {
1846 // only require color here, the font color will be defined
1847 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1849 features.require("color");
1850 features.require("fontcolor");
1853 // Only if class has a ToC hierarchy
1854 if (tclass.hasTocLevels()) {
1855 if (secnumdepth != tclass.secnumdepth()) {
1856 os << "\\setcounter{secnumdepth}{"
1860 if (tocdepth != tclass.tocdepth()) {
1861 os << "\\setcounter{tocdepth}{"
1867 if (paragraph_separation) {
1868 // when skip separation
1869 switch (getDefSkip().kind()) {
1870 case VSpace::SMALLSKIP:
1871 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1873 case VSpace::MEDSKIP:
1874 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1876 case VSpace::BIGSKIP:
1877 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1879 case VSpace::LENGTH:
1880 os << "\\setlength{\\parskip}{"
1881 << from_utf8(getDefSkip().length().asLatexString())
1884 default: // should never happen // Then delete it.
1885 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1888 os << "\\setlength{\\parindent}{0pt}\n";
1890 // when separation by indentation
1891 // only output something when a width is given
1892 if (getIndentation().asLyXCommand() != "default") {
1893 os << "\\setlength{\\parindent}{"
1894 << from_utf8(getIndentation().asLatexCommand())
1899 // Now insert the LyX specific LaTeX commands...
1900 features.resolveAlternatives();
1901 features.expandMultiples();
1904 if (!output_sync_macro.empty())
1905 os << from_utf8(output_sync_macro) +"\n";
1906 else if (features.runparams().flavor == OutputParams::LATEX)
1907 os << "\\usepackage[active]{srcltx}\n";
1908 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1909 os << "\\synctex=-1\n";
1912 // The package options (via \PassOptionsToPackage)
1913 os << from_ascii(features.getPackageOptions());
1915 // due to interferences with babel and hyperref, the color package has to
1916 // be loaded (when it is not already loaded) before babel when hyperref
1917 // is used with the colorlinks option, see
1918 // http://www.lyx.org/trac/ticket/5291
1919 // we decided therefore to load color always before babel, see
1920 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1921 os << from_ascii(features.getColorOptions());
1923 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1924 // we have to call babel before
1926 && (features.isRequired("jurabib")
1927 || features.isRequired("hyperref")
1928 || features.isRequired("varioref")
1929 || features.isRequired("vietnamese")
1930 || features.isRequired("japanese"))) {
1931 os << features.getBabelPresettings();
1933 os << from_utf8(babelCall(language_options.str(),
1934 features.needBabelLangOptions())) + '\n';
1935 os << features.getBabelPostsettings();
1938 // The optional packages;
1939 os << from_ascii(features.getPackages());
1941 // Additional Indices
1942 if (features.isRequired("splitidx")) {
1943 IndicesList::const_iterator iit = indiceslist().begin();
1944 IndicesList::const_iterator iend = indiceslist().end();
1945 for (; iit != iend; ++iit) {
1946 pair<docstring, docstring> indexname_latex =
1947 features.runparams().encoding->latexString(iit->index(),
1948 features.runparams().dryrun);
1949 if (!indexname_latex.second.empty()) {
1950 // issue a warning about omitted characters
1951 // FIXME: should be passed to the error dialog
1952 frontend::Alert::warning(_("Uncodable characters"),
1953 bformat(_("The following characters that are used in an index name are not\n"
1954 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1955 indexname_latex.second));
1957 os << "\\newindex[";
1958 os << indexname_latex.first;
1960 os << escape(iit->shortcut());
1966 os << from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1969 // * Hyperref manual: "Make sure it comes last of your loaded
1970 // packages, to give it a fighting chance of not being over-written,
1971 // since its job is to redefine many LaTeX commands."
1972 // * Email from Heiko Oberdiek: "It is usually better to load babel
1973 // before hyperref. Then hyperref has a chance to detect babel.
1974 // * Has to be loaded before the "LyX specific LaTeX commands" to
1975 // avoid errors with algorithm floats.
1976 // use hyperref explicitly if it is required
1977 if (features.isRequired("hyperref")) {
1978 OutputParams tmp_params = features.runparams();
1979 pdfoptions().writeLaTeX(tmp_params, os,
1980 features.isProvided("hyperref"));
1981 // correctly break URLs with hyperref and dvi output
1982 if (features.runparams().flavor == OutputParams::LATEX
1983 && features.isAvailable("breakurl"))
1984 os << "\\usepackage{breakurl}\n";
1985 } else if (features.isRequired("nameref"))
1986 // hyperref loads this automatically
1987 os << "\\usepackage{nameref}\n";
1989 // bibtopic needs to be loaded after hyperref.
1990 // the dot provides the aux file naming which LyX can detect.
1991 if (features.mustProvide("bibtopic"))
1992 os << "\\usepackage[dot]{bibtopic}\n";
1994 // Will be surrounded by \makeatletter and \makeatother when not empty
1995 otexstringstream atlyxpreamble;
1997 // Some macros LyX will need
1999 TexString tmppreamble = features.getMacros();
2000 if (!tmppreamble.str.empty())
2001 atlyxpreamble << "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2002 "LyX specific LaTeX commands.\n"
2003 << move(tmppreamble)
2006 // the text class specific preamble
2008 docstring tmppreamble = features.getTClassPreamble();
2009 if (!tmppreamble.empty())
2010 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2011 "Textclass specific LaTeX commands.\n"
2015 // suppress date if selected
2016 // use \@ifundefined because we cannot be sure that every document class
2017 // has a \date command
2019 atlyxpreamble << "\\@ifundefined{date}{}{\\date{}}\n";
2021 /* the user-defined preamble */
2022 if (!containsOnly(preamble, " \n\t")) {
2024 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2025 "User specified LaTeX commands.\n";
2027 // Check if the user preamble contains uncodable glyphs
2028 odocstringstream user_preamble;
2029 docstring uncodable_glyphs;
2030 Encoding const * const enc = features.runparams().encoding;
2032 for (size_t n = 0; n < preamble.size(); ++n) {
2033 char_type c = preamble[n];
2034 if (!enc->encodable(c)) {
2035 docstring const glyph(1, c);
2036 LYXERR0("Uncodable character '"
2038 << "' in user preamble!");
2039 uncodable_glyphs += glyph;
2040 if (features.runparams().dryrun) {
2041 user_preamble << "<" << _("LyX Warning: ")
2042 << _("uncodable character") << " '";
2043 user_preamble.put(c);
2044 user_preamble << "'>";
2047 user_preamble.put(c);
2050 user_preamble << preamble;
2052 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2053 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2054 frontend::Alert::warning(
2055 _("Uncodable character in user preamble"),
2057 _("The user preamble of your document contains glyphs "
2058 "that are unknown in the current document encoding "
2059 "(namely %1$s).\nThese glyphs are omitted "
2060 " from the output, which may result in "
2061 "incomplete output."
2062 "\n\nPlease select an appropriate "
2063 "document encoding\n"
2064 "(such as utf8) or change the "
2065 "preamble code accordingly."),
2068 atlyxpreamble << user_preamble.str() << '\n';
2071 // footmisc must be loaded after setspace
2072 // Load it here to avoid clashes with footmisc loaded in the user
2073 // preamble. For that reason we also pass the options via
2074 // \PassOptionsToPackage in getPreamble() and not here.
2075 if (features.mustProvide("footmisc"))
2076 atlyxpreamble << "\\usepackage{footmisc}\n";
2078 // subfig loads internally the LaTeX package "caption". As
2079 // caption is a very popular package, users will load it in
2080 // the preamble. Therefore we must load subfig behind the
2081 // user-defined preamble and check if the caption package was
2082 // loaded or not. For the case that caption is loaded before
2083 // subfig, there is the subfig option "caption=false". This
2084 // option also works when a koma-script class is used and
2085 // koma's own caption commands are used instead of caption. We
2086 // use \PassOptionsToPackage here because the user could have
2087 // already loaded subfig in the preamble.
2088 if (features.mustProvide("subfig"))
2089 atlyxpreamble << "\\@ifundefined{showcaptionsetup}{}{%\n"
2090 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2091 "\\usepackage{subfig}\n";
2093 // Itemize bullet settings need to be last in case the user
2094 // defines their own bullets that use a package included
2095 // in the user-defined preamble -- ARRae
2096 // Actually it has to be done much later than that
2097 // since some packages like frenchb make modifications
2098 // at \begin{document} time -- JMarc
2099 docstring bullets_def;
2100 for (int i = 0; i < 4; ++i) {
2101 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2102 if (bullets_def.empty())
2103 bullets_def += "\\AtBeginDocument{\n";
2104 bullets_def += " \\def\\labelitemi";
2106 // `i' is one less than the item to modify
2113 bullets_def += "ii";
2119 bullets_def += '{' +
2120 user_defined_bullet(i).getText()
2125 if (!bullets_def.empty())
2126 atlyxpreamble << bullets_def << "}\n\n";
2128 if (!atlyxpreamble.empty())
2129 os << "\n\\makeatletter\n"
2130 << atlyxpreamble.release()
2131 << "\\makeatother\n\n";
2133 // We try to load babel late, in case it interferes with other packages.
2134 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2135 // called after babel, though.
2136 if (use_babel && !features.isRequired("jurabib")
2137 && !features.isRequired("hyperref")
2138 && !features.isRequired("varioref")
2139 && !features.isRequired("vietnamese")
2140 && !features.isRequired("japanese")) {
2141 os << features.getBabelPresettings();
2143 os << from_utf8(babelCall(language_options.str(),
2144 features.needBabelLangOptions())) + '\n';
2145 os << features.getBabelPostsettings();
2147 if (features.isRequired("bicaption"))
2148 os << "\\usepackage{bicaption}\n";
2149 if (!listings_params.empty() || features.mustProvide("listings"))
2150 os << "\\usepackage{listings}\n";
2151 if (!listings_params.empty()) {
2153 // do not test validity because listings_params is
2154 // supposed to be valid
2156 InsetListingsParams(listings_params).separatedParams(true);
2157 os << from_utf8(par);
2161 // xunicode needs to be loaded at least after amsmath, amssymb,
2162 // esint and the other packages that provide special glyphs
2163 // The package only supports XeTeX currently.
2164 if (features.runparams().flavor == OutputParams::XETEX
2166 os << "\\usepackage{xunicode}\n";
2168 // Polyglossia must be loaded last
2169 if (use_polyglossia) {
2171 os << "\\usepackage{polyglossia}\n";
2172 // set the main language
2173 os << "\\setdefaultlanguage";
2174 if (!language->polyglossiaOpts().empty())
2175 os << "[" << from_ascii(language->polyglossiaOpts()) << "]";
2176 os << "{" << from_ascii(language->polyglossia()) << "}\n";
2177 // now setup the other languages
2178 set<string> const polylangs =
2179 features.getPolyglossiaLanguages();
2180 for (set<string>::const_iterator mit = polylangs.begin();
2181 mit != polylangs.end() ; ++mit) {
2182 // We do not output the options here; they are output in
2183 // the language switch commands. This is safer if multiple
2184 // varieties are used.
2185 if (*mit == language->polyglossia())
2187 os << "\\setotherlanguage";
2188 os << "{" << from_ascii(*mit) << "}\n";
2192 // Load custom language package here
2193 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2194 if (lang_package == "default")
2195 os << from_utf8(lyxrc.language_custom_package);
2197 os << from_utf8(lang_package);
2201 docstring const i18npreamble =
2202 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2203 if (!i18npreamble.empty())
2204 os << i18npreamble + '\n';
2210 void BufferParams::useClassDefaults()
2212 DocumentClass const & tclass = documentClass();
2214 sides = tclass.sides();
2215 columns = tclass.columns();
2216 pagestyle = tclass.pagestyle();
2217 use_default_options = true;
2218 // Only if class has a ToC hierarchy
2219 if (tclass.hasTocLevels()) {
2220 secnumdepth = tclass.secnumdepth();
2221 tocdepth = tclass.tocdepth();
2226 bool BufferParams::hasClassDefaults() const
2228 DocumentClass const & tclass = documentClass();
2230 return sides == tclass.sides()
2231 && columns == tclass.columns()
2232 && pagestyle == tclass.pagestyle()
2233 && use_default_options
2234 && secnumdepth == tclass.secnumdepth()
2235 && tocdepth == tclass.tocdepth();
2239 DocumentClass const & BufferParams::documentClass() const
2245 DocumentClassConstPtr BufferParams::documentClassPtr() const
2251 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2253 // evil, but this function is evil
2254 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2255 invalidateConverterCache();
2259 bool BufferParams::setBaseClass(string const & classname)
2261 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2262 LayoutFileList & bcl = LayoutFileList::get();
2263 if (!bcl.haveClass(classname)) {
2265 bformat(_("The layout file:\n"
2267 "could not be found. A default textclass with default\n"
2268 "layouts will be used. LyX will not be able to produce\n"
2270 from_utf8(classname));
2271 frontend::Alert::error(_("Document class not found"), s);
2272 bcl.addEmptyClass(classname);
2275 bool const success = bcl[classname].load();
2278 bformat(_("Due to some error in it, the layout file:\n"
2280 "could not be loaded. A default textclass with default\n"
2281 "layouts will be used. LyX will not be able to produce\n"
2283 from_utf8(classname));
2284 frontend::Alert::error(_("Could not load class"), s);
2285 bcl.addEmptyClass(classname);
2288 pimpl_->baseClass_ = classname;
2289 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2294 LayoutFile const * BufferParams::baseClass() const
2296 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2297 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2303 LayoutFileIndex const & BufferParams::baseClassID() const
2305 return pimpl_->baseClass_;
2309 void BufferParams::makeDocumentClass(bool const clone)
2314 invalidateConverterCache();
2315 LayoutModuleList mods;
2316 LayoutModuleList ces;
2317 LayoutModuleList::iterator it = layout_modules_.begin();
2318 LayoutModuleList::iterator en = layout_modules_.end();
2319 for (; it != en; ++it)
2320 mods.push_back(*it);
2322 it = cite_engine_.begin();
2323 en = cite_engine_.end();
2324 for (; it != en; ++it)
2327 doc_class_ = getDocumentClass(*baseClass(), mods, ces, clone);
2329 TextClass::ReturnValues success = TextClass::OK;
2330 if (!forced_local_layout_.empty())
2331 success = doc_class_->read(to_utf8(forced_local_layout_),
2333 if (!local_layout_.empty() &&
2334 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2335 success = doc_class_->read(to_utf8(local_layout_), TextClass::MODULE);
2336 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2337 docstring const msg = _("Error reading internal layout information");
2338 frontend::Alert::warning(_("Read Error"), msg);
2343 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2345 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2349 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2351 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2355 docstring BufferParams::getLocalLayout(bool forced) const
2358 return from_utf8(doc_class_->forcedLayouts());
2360 return local_layout_;
2364 void BufferParams::setLocalLayout(docstring const & layout, bool forced)
2367 forced_local_layout_ = layout;
2369 local_layout_ = layout;
2373 bool BufferParams::addLayoutModule(string const & modName)
2375 LayoutModuleList::const_iterator it = layout_modules_.begin();
2376 LayoutModuleList::const_iterator end = layout_modules_.end();
2377 for (; it != end; ++it)
2380 layout_modules_.push_back(modName);
2385 string BufferParams::bufferFormat() const
2387 return documentClass().outputFormat();
2391 bool BufferParams::isExportable(string const & format, bool need_viewable) const
2393 FormatList const & formats = exportableFormats(need_viewable);
2394 FormatList::const_iterator fit = formats.begin();
2395 FormatList::const_iterator end = formats.end();
2396 for (; fit != end ; ++fit) {
2397 if ((*fit)->name() == format)
2404 FormatList const & BufferParams::exportableFormats(bool only_viewable) const
2406 FormatList & cached = only_viewable ?
2407 pimpl_->viewableFormatList : pimpl_->exportableFormatList;
2408 bool & valid = only_viewable ?
2409 pimpl_->isViewCacheValid : pimpl_->isExportCacheValid;
2413 vector<string> const backs = backends();
2414 set<string> excludes;
2415 if (useNonTeXFonts) {
2416 excludes.insert("latex");
2417 excludes.insert("pdflatex");
2420 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2421 for (vector<string>::const_iterator it = backs.begin() + 1;
2422 it != backs.end(); ++it) {
2423 FormatList r = theConverters().getReachable(*it, only_viewable,
2425 result.insert(result.end(), r.begin(), r.end());
2427 sort(result.begin(), result.end(), Format::formatSorter);
2434 vector<string> BufferParams::backends() const
2437 string const buffmt = bufferFormat();
2439 // FIXME: Don't hardcode format names here, but use a flag
2440 if (buffmt == "latex") {
2441 if (encoding().package() == Encoding::japanese)
2442 v.push_back("platex");
2444 if (!useNonTeXFonts) {
2445 v.push_back("pdflatex");
2446 v.push_back("latex");
2448 v.push_back("xetex");
2449 v.push_back("luatex");
2450 v.push_back("dviluatex");
2453 v.push_back(buffmt);
2455 v.push_back("xhtml");
2456 v.push_back("text");
2462 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2464 string const dformat = (format.empty() || format == "default") ?
2465 getDefaultOutputFormat() : format;
2466 DefaultFlavorCache::const_iterator it =
2467 default_flavors_.find(dformat);
2469 if (it != default_flavors_.end())
2472 OutputParams::FLAVOR result = OutputParams::LATEX;
2474 // FIXME It'd be better not to hardcode this, but to do
2475 // something with formats.
2476 if (dformat == "xhtml")
2477 result = OutputParams::HTML;
2478 else if (dformat == "text")
2479 result = OutputParams::TEXT;
2480 else if (dformat == "lyx")
2481 result = OutputParams::LYX;
2482 else if (dformat == "pdflatex")
2483 result = OutputParams::PDFLATEX;
2484 else if (dformat == "xetex")
2485 result = OutputParams::XETEX;
2486 else if (dformat == "luatex")
2487 result = OutputParams::LUATEX;
2488 else if (dformat == "dviluatex")
2489 result = OutputParams::DVILUATEX;
2491 // Try to determine flavor of default output format
2492 vector<string> backs = backends();
2493 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2494 // Get shortest path to format
2495 Graph::EdgePath path;
2496 for (vector<string>::const_iterator it = backs.begin();
2497 it != backs.end(); ++it) {
2498 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2499 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2504 result = theConverters().getFlavor(path);
2507 // cache this flavor
2508 default_flavors_[dformat] = result;
2513 string BufferParams::getDefaultOutputFormat() const
2515 if (!default_output_format.empty()
2516 && default_output_format != "default")
2517 return default_output_format;
2519 || encoding().package() == Encoding::japanese) {
2520 FormatList const & formats = exportableFormats(true);
2521 if (formats.empty())
2523 // return the first we find
2524 return formats.front()->name();
2527 return lyxrc.default_otf_view_format;
2528 return lyxrc.default_view_format;
2531 Font const BufferParams::getFont() const
2533 FontInfo f = documentClass().defaultfont();
2534 if (fonts_default_family == "rmdefault")
2535 f.setFamily(ROMAN_FAMILY);
2536 else if (fonts_default_family == "sfdefault")
2537 f.setFamily(SANS_FAMILY);
2538 else if (fonts_default_family == "ttdefault")
2539 f.setFamily(TYPEWRITER_FAMILY);
2540 return Font(f, language);
2544 InsetQuotesParams::QuoteStyle BufferParams::getQuoteStyle(string const & qs) const
2546 return quotesstyletranslator().find(qs);
2550 bool BufferParams::isLatex() const
2552 return documentClass().outputType() == LATEX;
2556 bool BufferParams::isLiterate() const
2558 return documentClass().outputType() == LITERATE;
2562 bool BufferParams::isDocBook() const
2564 return documentClass().outputType() == DOCBOOK;
2568 void BufferParams::readPreamble(Lexer & lex)
2570 if (lex.getString() != "\\begin_preamble")
2571 lyxerr << "Error (BufferParams::readPreamble):"
2572 "consistency check failed." << endl;
2574 preamble = lex.getLongString(from_ascii("\\end_preamble"));
2578 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2580 string const expected = forced ? "\\begin_forced_local_layout" :
2581 "\\begin_local_layout";
2582 if (lex.getString() != expected)
2583 lyxerr << "Error (BufferParams::readLocalLayout):"
2584 "consistency check failed." << endl;
2587 forced_local_layout_ =
2588 lex.getLongString(from_ascii("\\end_forced_local_layout"));
2590 local_layout_ = lex.getLongString(from_ascii("\\end_local_layout"));
2594 bool BufferParams::setLanguage(string const & lang)
2596 Language const *new_language = languages.getLanguage(lang);
2597 if (!new_language) {
2598 // Language lang was not found
2601 language = new_language;
2606 void BufferParams::readLanguage(Lexer & lex)
2608 if (!lex.next()) return;
2610 string const tmptok = lex.getString();
2612 // check if tmptok is part of tex_babel in tex-defs.h
2613 if (!setLanguage(tmptok)) {
2614 // Language tmptok was not found
2615 language = default_language;
2616 lyxerr << "Warning: Setting language `"
2617 << tmptok << "' to `" << language->lang()
2623 void BufferParams::readGraphicsDriver(Lexer & lex)
2628 string const tmptok = lex.getString();
2629 // check if tmptok is part of tex_graphics in tex_defs.h
2632 string const test = tex_graphics[n++];
2634 if (test == tmptok) {
2635 graphics_driver = tmptok;
2640 "Warning: graphics driver `$$Token' not recognized!\n"
2641 " Setting graphics driver to `default'.\n");
2642 graphics_driver = "default";
2649 void BufferParams::readBullets(Lexer & lex)
2654 int const index = lex.getInteger();
2656 int temp_int = lex.getInteger();
2657 user_defined_bullet(index).setFont(temp_int);
2658 temp_bullet(index).setFont(temp_int);
2660 user_defined_bullet(index).setCharacter(temp_int);
2661 temp_bullet(index).setCharacter(temp_int);
2663 user_defined_bullet(index).setSize(temp_int);
2664 temp_bullet(index).setSize(temp_int);
2668 void BufferParams::readBulletsLaTeX(Lexer & lex)
2670 // The bullet class should be able to read this.
2673 int const index = lex.getInteger();
2675 docstring const temp_str = lex.getDocString();
2677 user_defined_bullet(index).setText(temp_str);
2678 temp_bullet(index).setText(temp_str);
2682 void BufferParams::readModules(Lexer & lex)
2684 if (!lex.eatLine()) {
2685 lyxerr << "Error (BufferParams::readModules):"
2686 "Unexpected end of input." << endl;
2690 string mod = lex.getString();
2691 if (mod == "\\end_modules")
2693 addLayoutModule(mod);
2699 void BufferParams::readRemovedModules(Lexer & lex)
2701 if (!lex.eatLine()) {
2702 lyxerr << "Error (BufferParams::readRemovedModules):"
2703 "Unexpected end of input." << endl;
2707 string mod = lex.getString();
2708 if (mod == "\\end_removed_modules")
2710 removed_modules_.push_back(mod);
2713 // now we want to remove any removed modules that were previously
2714 // added. normally, that will be because default modules were added in
2715 // setBaseClass(), which gets called when \textclass is read at the
2716 // start of the read.
2717 list<string>::const_iterator rit = removed_modules_.begin();
2718 list<string>::const_iterator const ren = removed_modules_.end();
2719 for (; rit != ren; ++rit) {
2720 LayoutModuleList::iterator const mit = layout_modules_.begin();
2721 LayoutModuleList::iterator const men = layout_modules_.end();
2722 LayoutModuleList::iterator found = find(mit, men, *rit);
2725 layout_modules_.erase(found);
2730 void BufferParams::readIncludeonly(Lexer & lex)
2732 if (!lex.eatLine()) {
2733 lyxerr << "Error (BufferParams::readIncludeonly):"
2734 "Unexpected end of input." << endl;
2738 string child = lex.getString();
2739 if (child == "\\end_includeonly")
2741 included_children_.push_back(child);
2747 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2749 switch (papersize) {
2751 // could be anything, so don't guess
2753 case PAPER_CUSTOM: {
2754 if (purpose == XDVI && !paperwidth.empty() &&
2755 !paperheight.empty()) {
2756 // heightxwidth<unit>
2757 string first = paperwidth;
2758 string second = paperheight;
2759 if (orientation == ORIENTATION_LANDSCAPE)
2762 return first.erase(first.length() - 2)
2768 // dvips and dvipdfm do not know this
2769 if (purpose == DVIPS || purpose == DVIPDFM)
2773 if (purpose == DVIPS || purpose == DVIPDFM)
2777 if (purpose == DVIPS || purpose == DVIPDFM)
2787 if (purpose == DVIPS || purpose == DVIPDFM)
2791 if (purpose == DVIPS || purpose == DVIPDFM)
2795 if (purpose == DVIPS || purpose == DVIPDFM)
2799 if (purpose == DVIPS || purpose == DVIPDFM)
2803 if (purpose == DVIPS || purpose == DVIPDFM)
2807 // dvipdfm does not know this
2808 if (purpose == DVIPDFM)
2812 if (purpose == DVIPDFM)
2816 if (purpose == DVIPS || purpose == DVIPDFM)
2820 if (purpose == DVIPS || purpose == DVIPDFM)
2824 if (purpose == DVIPS || purpose == DVIPDFM)
2828 if (purpose == DVIPS || purpose == DVIPDFM)
2832 if (purpose == DVIPS || purpose == DVIPDFM)
2836 if (purpose == DVIPS || purpose == DVIPDFM)
2840 if (purpose == DVIPS || purpose == DVIPDFM)
2844 if (purpose == DVIPS || purpose == DVIPDFM)
2848 if (purpose == DVIPS || purpose == DVIPDFM)
2852 if (purpose == DVIPS || purpose == DVIPDFM)
2856 if (purpose == DVIPS || purpose == DVIPDFM)
2860 if (purpose == DVIPS || purpose == DVIPDFM)
2864 if (purpose == DVIPS || purpose == DVIPDFM)
2868 if (purpose == DVIPS || purpose == DVIPDFM)
2872 if (purpose == DVIPS || purpose == DVIPDFM)
2875 case PAPER_USEXECUTIVE:
2876 // dvipdfm does not know this
2877 if (purpose == DVIPDFM)
2882 case PAPER_USLETTER:
2884 if (purpose == XDVI)
2891 string const BufferParams::dvips_options() const
2895 // If the class loads the geometry package, we do not know which
2896 // paper size is used, since we do not set it (bug 7013).
2897 // Therefore we must not specify any argument here.
2898 // dvips gets the correct paper size via DVI specials in this case
2899 // (if the class uses the geometry package correctly).
2900 if (documentClass().provides("geometry"))
2904 && papersize == PAPER_CUSTOM
2905 && !lyxrc.print_paper_dimension_flag.empty()
2906 && !paperwidth.empty()
2907 && !paperheight.empty()) {
2908 // using a custom papersize
2909 result = lyxrc.print_paper_dimension_flag;
2910 result += ' ' + paperwidth;
2911 result += ',' + paperheight;
2913 string const paper_option = paperSizeName(DVIPS);
2914 if (!paper_option.empty() && (paper_option != "letter" ||
2915 orientation != ORIENTATION_LANDSCAPE)) {
2916 // dvips won't accept -t letter -t landscape.
2917 // In all other cases, include the paper size
2919 result = lyxrc.print_paper_flag;
2920 result += ' ' + paper_option;
2923 if (orientation == ORIENTATION_LANDSCAPE &&
2924 papersize != PAPER_CUSTOM)
2925 result += ' ' + lyxrc.print_landscape_flag;
2930 string const BufferParams::font_encoding() const
2932 return font_encodings().empty() ? "default" : font_encodings().back();
2936 vector<string> const BufferParams::font_encodings() const
2938 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2940 vector<string> fontencs;
2942 // "default" means "no explicit font encoding"
2943 if (doc_fontenc != "default") {
2944 fontencs = getVectorFromString(doc_fontenc);
2945 if (!language->fontenc().empty()
2946 && ascii_lowercase(language->fontenc()) != "none") {
2947 vector<string> fencs = getVectorFromString(language->fontenc());
2948 vector<string>::const_iterator fit = fencs.begin();
2949 for (; fit != fencs.end(); ++fit) {
2950 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2951 fontencs.push_back(*fit);
2960 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2962 // suppress the babel call if there is no BabelName defined
2963 // for the document language in the lib/languages file and if no
2964 // other languages are used (lang_opts is then empty)
2965 if (lang_opts.empty())
2967 // either a specific language (AsBabelOptions setting in
2968 // lib/languages) or the prefs require the languages to
2969 // be submitted to babel itself (not the class).
2971 return "\\usepackage[" + lang_opts + "]{babel}";
2972 return "\\usepackage{babel}";
2976 docstring BufferParams::getGraphicsDriver(string const & package) const
2980 if (package == "geometry") {
2981 if (graphics_driver == "dvips"
2982 || graphics_driver == "dvipdfm"
2983 || graphics_driver == "pdftex"
2984 || graphics_driver == "vtex")
2985 result = from_ascii(graphics_driver);
2986 else if (graphics_driver == "dvipdfmx")
2987 result = from_ascii("dvipdfm");
2994 void BufferParams::writeEncodingPreamble(otexstream & os,
2995 LaTeXFeatures & features) const
2997 // XeTeX/LuaTeX: (see also #9740)
2998 // With Unicode fonts we use utf8-plain without encoding package.
2999 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
3000 // XeTeX must use ASCII encoding (see Buffer.cpp),
3001 // for LuaTeX, we load "luainputenc" (see below).
3002 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
3005 if (inputenc == "auto") {
3006 string const doc_encoding =
3007 language->encoding()->latexName();
3008 Encoding::Package const package =
3009 language->encoding()->package();
3011 // Create list of inputenc options:
3012 set<string> encodings;
3013 // luainputenc fails with more than one encoding
3014 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
3015 // list all input encodings used in the document
3016 encodings = features.getEncodingSet(doc_encoding);
3018 // If the "japanese" package (i.e. pLaTeX) is used,
3019 // inputenc must be omitted.
3020 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
3021 if ((!encodings.empty() || package == Encoding::inputenc)
3022 && !features.isRequired("japanese")
3023 && !features.isProvided("inputenc")) {
3024 os << "\\usepackage[";
3025 set<string>::const_iterator it = encodings.begin();
3026 set<string>::const_iterator const end = encodings.end();
3028 os << from_ascii(*it);
3031 for (; it != end; ++it)
3032 os << ',' << from_ascii(*it);
3033 if (package == Encoding::inputenc) {
3034 if (!encodings.empty())
3036 os << from_ascii(doc_encoding);
3038 if (features.runparams().flavor == OutputParams::LUATEX
3039 || features.runparams().flavor == OutputParams::DVILUATEX)
3040 os << "]{luainputenc}\n";
3042 os << "]{inputenc}\n";
3044 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3045 if (language->encoding()->name() == "utf8-cjk"
3046 && LaTeXFeatures::isAvailable("CJKutf8"))
3047 os << "\\usepackage{CJKutf8}\n";
3049 os << "\\usepackage{CJK}\n";
3051 } else if (inputenc != "default") {
3052 switch (encoding().package()) {
3053 case Encoding::none:
3054 case Encoding::japanese:
3056 case Encoding::inputenc:
3057 // do not load inputenc if japanese is used
3058 // or if the class provides inputenc
3059 if (features.isRequired("japanese")
3060 || features.isProvided("inputenc"))
3062 os << "\\usepackage[" << from_ascii(encoding().latexName());
3063 if (features.runparams().flavor == OutputParams::LUATEX
3064 || features.runparams().flavor == OutputParams::DVILUATEX)
3065 os << "]{luainputenc}\n";
3067 os << "]{inputenc}\n";
3070 if (encoding().name() == "utf8-cjk"
3071 && LaTeXFeatures::isAvailable("CJKutf8"))
3072 os << "\\usepackage{CJKutf8}\n";
3074 os << "\\usepackage{CJK}\n";
3077 // Load the CJK package if needed by a secondary language.
3078 // If the main encoding is some variant of UTF8, use CJKutf8.
3079 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3080 if (encoding().iconvName() == "UTF-8"
3081 && LaTeXFeatures::isAvailable("CJKutf8"))
3082 os << "\\usepackage{CJKutf8}\n";
3084 os << "\\usepackage{CJK}\n";
3090 string const BufferParams::parseFontName(string const & name) const
3092 string mangled = name;
3093 size_t const idx = mangled.find('[');
3094 if (idx == string::npos || idx == 0)
3097 return mangled.substr(0, idx - 1);
3101 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3103 if (fontsRoman() == "default" && fontsSans() == "default"
3104 && fontsTypewriter() == "default"
3105 && (fontsMath() == "default" || fontsMath() == "auto"))
3111 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3112 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3113 * Mapping=tex-text option assures TeX ligatures (such as "--")
3114 * are resolved. Note that tt does not use these ligatures.
3116 * -- add more GUI options?
3117 * -- add more fonts (fonts for other scripts)
3118 * -- if there's a way to find out if a font really supports
3119 * OldStyle, enable/disable the widget accordingly.
3121 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3122 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3123 // However, until v.2 (2010/07/11) fontspec only knew
3124 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3125 // was introduced for both XeTeX and LuaTeX (LuaTeX
3126 // didn't understand "Mapping=tex-text", while XeTeX
3127 // understood both. With most recent versions, both
3128 // variants are understood by both engines. However,
3129 // we want to provide support for at least TeXLive 2009
3130 // (for XeTeX; LuaTeX is only supported as of v.2)
3131 string const texmapping =
3132 (features.runparams().flavor == OutputParams::XETEX) ?
3133 "Mapping=tex-text" : "Ligatures=TeX";
3134 if (fontsRoman() != "default") {
3135 os << "\\setmainfont[" << texmapping;
3136 if (fonts_old_figures)
3137 os << ",Numbers=OldStyle";
3138 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3140 if (fontsSans() != "default") {
3141 string const sans = parseFontName(fontsSans());
3142 if (fontsSansScale() != 100)
3143 os << "\\setsansfont[Scale="
3144 << float(fontsSansScale()) / 100
3145 << "," << texmapping << "]{"
3148 os << "\\setsansfont[" << texmapping << "]{"
3151 if (fontsTypewriter() != "default") {
3152 string const mono = parseFontName(fontsTypewriter());
3153 if (fontsTypewriterScale() != 100)
3154 os << "\\setmonofont[Scale="
3155 << float(fontsTypewriterScale()) / 100
3159 os << "\\setmonofont{"
3166 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3167 bool const dryrun = features.runparams().dryrun;
3168 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3169 bool const nomath = (fontsMath() == "default");
3172 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3173 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3177 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3178 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3179 nomath, fontsSansScale());
3181 // MONOSPACED/TYPEWRITER
3182 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3183 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3184 nomath, fontsTypewriterScale());
3187 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3188 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3195 Encoding const & BufferParams::encoding() const
3197 // Main encoding for LaTeX output.
3199 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3200 // As the "flavor" is only known once export started, this
3201 // cannot be handled here. Instead, runparams.encoding is set
3202 // to ASCII in Buffer::makeLaTeXFile (for export)
3203 // and Buffer::writeLaTeXSource (for preview).
3205 return *(encodings.fromLyXName("utf8-plain"));
3206 if (inputenc == "auto" || inputenc == "default")
3207 return *language->encoding();
3208 Encoding const * const enc = encodings.fromLyXName(inputenc);
3211 LYXERR0("Unknown inputenc value `" << inputenc
3212 << "'. Using `auto' instead.");
3213 return *language->encoding();
3217 bool BufferParams::addCiteEngine(string const & engine)
3219 LayoutModuleList::const_iterator it = cite_engine_.begin();
3220 LayoutModuleList::const_iterator en = cite_engine_.end();
3221 for (; it != en; ++it)
3224 cite_engine_.push_back(engine);
3229 bool BufferParams::addCiteEngine(vector<string> const & engine)
3231 vector<string>::const_iterator it = engine.begin();
3232 vector<string>::const_iterator en = engine.end();
3234 for (; it != en; ++it)
3235 if (!addCiteEngine(*it))
3241 string const & BufferParams::defaultBiblioStyle() const
3243 map<string, string> bs = documentClass().defaultBiblioStyle();
3244 return bs[theCiteEnginesList.getTypeAsString(citeEngineType())];
3248 bool const & BufferParams::fullAuthorList() const
3250 return documentClass().fullAuthorList();
3254 string BufferParams::getCiteAlias(string const & s) const
3256 vector<string> commands =
3257 documentClass().citeCommands(citeEngineType());
3258 // If it is a real command, don't treat it as an alias
3259 if (find(commands.begin(), commands.end(), s) != commands.end())
3261 map<string,string> aliases = documentClass().citeCommandAliases();
3262 if (aliases.find(s) != aliases.end())
3268 void BufferParams::setCiteEngine(string const & engine)
3271 addCiteEngine(engine);
3275 void BufferParams::setCiteEngine(vector<string> const & engine)
3278 addCiteEngine(engine);
3282 vector<string> BufferParams::citeCommands() const
3284 static CitationStyle const default_style;
3285 vector<string> commands =
3286 documentClass().citeCommands(citeEngineType());
3287 if (commands.empty())
3288 commands.push_back(default_style.name);
3293 vector<CitationStyle> BufferParams::citeStyles() const
3295 static CitationStyle const default_style;
3296 vector<CitationStyle> styles =
3297 documentClass().citeStyles(citeEngineType());
3299 styles.push_back(default_style);
3304 string const & BufferParams::bibtexCommand() const
3306 if (bibtex_command != "default")
3307 return bibtex_command;
3308 else if (encoding().package() == Encoding::japanese)
3309 return lyxrc.jbibtex_command;
3311 return lyxrc.bibtex_command;
3315 void BufferParams::invalidateConverterCache() const
3317 pimpl_->isExportCacheValid = false;
3318 pimpl_->isViewCacheValid = false;