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"
28 #include "Converter.h"
31 #include "IndicesList.h"
33 #include "LaTeXFeatures.h"
34 #include "LaTeXFonts.h"
35 #include "ModuleList.h"
39 #include "OutputParams.h"
41 #include "texstream.h"
44 #include "PDFOptions.h"
46 #include "frontends/alert.h"
48 #include "insets/InsetListingsParams.h"
50 #include "support/convert.h"
51 #include "support/debug.h"
52 #include "support/docstream.h"
53 #include "support/FileName.h"
54 #include "support/filetools.h"
55 #include "support/gettext.h"
56 #include "support/Messages.h"
57 #include "support/mutex.h"
58 #include "support/Package.h"
59 #include "support/Translator.h"
60 #include "support/lstrings.h"
66 using namespace lyx::support;
69 static char const * const string_paragraph_separation[] = {
74 static char const * const string_quotes_style[] = {
75 "english", "swedish", "german", "polish", "swiss", "danish", "plain",
76 "british", "swedishg", "french", "frenchin", "russian", "cjk", "cjkangle", ""
80 static char const * const string_papersize[] = {
81 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
82 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
83 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
84 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
85 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
90 static char const * const string_orientation[] = {
91 "portrait", "landscape", ""
95 static char const * const tex_graphics[] = {
96 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
97 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
98 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
99 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
110 // Paragraph separation
111 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
114 ParSepTranslator const init_parseptranslator()
116 ParSepTranslator translator
117 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
118 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
123 ParSepTranslator const & parseptranslator()
125 static ParSepTranslator const translator =
126 init_parseptranslator();
132 typedef Translator<string, InsetQuotesParams::QuoteStyle> QuotesStyleTranslator;
135 QuotesStyleTranslator const init_quotesstyletranslator()
137 QuotesStyleTranslator translator
138 (string_quotes_style[0], InsetQuotesParams::EnglishQuotes);
139 translator.addPair(string_quotes_style[1], InsetQuotesParams::SwedishQuotes);
140 translator.addPair(string_quotes_style[2], InsetQuotesParams::GermanQuotes);
141 translator.addPair(string_quotes_style[3], InsetQuotesParams::PolishQuotes);
142 translator.addPair(string_quotes_style[4], InsetQuotesParams::SwissQuotes);
143 translator.addPair(string_quotes_style[5], InsetQuotesParams::DanishQuotes);
144 translator.addPair(string_quotes_style[6], InsetQuotesParams::PlainQuotes);
145 translator.addPair(string_quotes_style[7], InsetQuotesParams::BritishQuotes);
146 translator.addPair(string_quotes_style[8], InsetQuotesParams::SwedishGQuotes);
147 translator.addPair(string_quotes_style[9], InsetQuotesParams::FrenchQuotes);
148 translator.addPair(string_quotes_style[10], InsetQuotesParams::FrenchINQuotes);
149 translator.addPair(string_quotes_style[11], InsetQuotesParams::RussianQuotes);
150 translator.addPair(string_quotes_style[12], InsetQuotesParams::CJKQuotes);
151 translator.addPair(string_quotes_style[13], InsetQuotesParams::CJKAngleQuotes);
156 QuotesStyleTranslator const & quotesstyletranslator()
158 static QuotesStyleTranslator const translator =
159 init_quotesstyletranslator();
165 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
168 static PaperSizeTranslator initPaperSizeTranslator()
170 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
171 translator.addPair(string_papersize[1], PAPER_CUSTOM);
172 translator.addPair(string_papersize[2], PAPER_USLETTER);
173 translator.addPair(string_papersize[3], PAPER_USLEGAL);
174 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
175 translator.addPair(string_papersize[5], PAPER_A0);
176 translator.addPair(string_papersize[6], PAPER_A1);
177 translator.addPair(string_papersize[7], PAPER_A2);
178 translator.addPair(string_papersize[8], PAPER_A3);
179 translator.addPair(string_papersize[9], PAPER_A4);
180 translator.addPair(string_papersize[10], PAPER_A5);
181 translator.addPair(string_papersize[11], PAPER_A6);
182 translator.addPair(string_papersize[12], PAPER_B0);
183 translator.addPair(string_papersize[13], PAPER_B1);
184 translator.addPair(string_papersize[14], PAPER_B2);
185 translator.addPair(string_papersize[15], PAPER_B3);
186 translator.addPair(string_papersize[16], PAPER_B4);
187 translator.addPair(string_papersize[17], PAPER_B5);
188 translator.addPair(string_papersize[18], PAPER_B6);
189 translator.addPair(string_papersize[19], PAPER_C0);
190 translator.addPair(string_papersize[20], PAPER_C1);
191 translator.addPair(string_papersize[21], PAPER_C2);
192 translator.addPair(string_papersize[22], PAPER_C3);
193 translator.addPair(string_papersize[23], PAPER_C4);
194 translator.addPair(string_papersize[24], PAPER_C5);
195 translator.addPair(string_papersize[25], PAPER_C6);
196 translator.addPair(string_papersize[26], PAPER_JISB0);
197 translator.addPair(string_papersize[27], PAPER_JISB1);
198 translator.addPair(string_papersize[28], PAPER_JISB2);
199 translator.addPair(string_papersize[29], PAPER_JISB3);
200 translator.addPair(string_papersize[30], PAPER_JISB4);
201 translator.addPair(string_papersize[31], PAPER_JISB5);
202 translator.addPair(string_papersize[32], PAPER_JISB6);
207 PaperSizeTranslator const & papersizetranslator()
209 static PaperSizeTranslator const translator =
210 initPaperSizeTranslator();
216 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
219 PaperOrientationTranslator const init_paperorientationtranslator()
221 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
222 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
227 PaperOrientationTranslator const & paperorientationtranslator()
229 static PaperOrientationTranslator const translator =
230 init_paperorientationtranslator();
236 typedef Translator<int, PageSides> SidesTranslator;
239 SidesTranslator const init_sidestranslator()
241 SidesTranslator translator(1, OneSide);
242 translator.addPair(2, TwoSides);
247 SidesTranslator const & sidestranslator()
249 static SidesTranslator const translator = init_sidestranslator();
255 typedef Translator<int, BufferParams::Package> PackageTranslator;
258 PackageTranslator const init_packagetranslator()
260 PackageTranslator translator(0, BufferParams::package_off);
261 translator.addPair(1, BufferParams::package_auto);
262 translator.addPair(2, BufferParams::package_on);
267 PackageTranslator const & packagetranslator()
269 static PackageTranslator const translator =
270 init_packagetranslator();
276 typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
279 CiteEngineTypeTranslator const init_citeenginetypetranslator()
281 CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
282 translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
283 translator.addPair("default", ENGINE_TYPE_DEFAULT);
288 CiteEngineTypeTranslator const & citeenginetypetranslator()
290 static CiteEngineTypeTranslator const translator =
291 init_citeenginetypetranslator();
297 typedef Translator<string, Spacing::Space> SpaceTranslator;
300 SpaceTranslator const init_spacetranslator()
302 SpaceTranslator translator("default", Spacing::Default);
303 translator.addPair("single", Spacing::Single);
304 translator.addPair("onehalf", Spacing::Onehalf);
305 translator.addPair("double", Spacing::Double);
306 translator.addPair("other", Spacing::Other);
311 SpaceTranslator const & spacetranslator()
313 static SpaceTranslator const translator = init_spacetranslator();
318 bool inSystemDir(FileName const & document_dir, string & system_dir)
320 // A document is assumed to be in a system LyX directory (not
321 // necessarily the system directory of the running instance)
322 // if both "configure.py" and "chkconfig.ltx" are found in
323 // either document_dir/../ or document_dir/../../.
324 // If true, the system directory path is returned in system_dir
325 // with a trailing path separator.
327 string const msg = "Checking whether document is in a system dir...";
329 string dir = document_dir.absFileName();
331 for (int i = 0; i < 2; ++i) {
332 dir = addPath(dir, "..");
333 if (!fileSearch(dir, "configure.py").empty() &&
334 !fileSearch(dir, "chkconfig.ltx").empty()) {
335 LYXERR(Debug::FILES, msg << " yes");
336 system_dir = addPath(FileName(dir).realPath(), "");
341 LYXERR(Debug::FILES, msg << " no");
342 system_dir = string();
349 class BufferParams::Impl
354 AuthorList authorlist;
355 BranchList branchlist;
356 Bullet temp_bullets[4];
357 Bullet user_defined_bullets[4];
358 IndicesList indiceslist;
360 /** This is the amount of space used for paragraph_separation "skip",
361 * and for detached paragraphs in "indented" documents.
365 PDFOptions pdfoptions;
366 LayoutFileIndex baseClass_;
367 FormatList exportableFormatList;
368 FormatList viewableFormatList;
369 bool isViewCacheValid;
370 bool isExportCacheValid;
374 BufferParams::Impl::Impl()
375 : defskip(VSpace::MEDSKIP), baseClass_(string("")),
376 isViewCacheValid(false), isExportCacheValid(false)
378 // set initial author
380 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
385 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
388 return new BufferParams::Impl(*ptr);
392 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
398 BufferParams::BufferParams()
401 setBaseClass(defaultBaseclass());
402 cite_engine_.push_back("basic");
403 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
405 paragraph_separation = ParagraphIndentSeparation;
406 quotes_style = InsetQuotesParams::EnglishQuotes;
407 dynamic_quotes = false;
408 fontsize = "default";
411 papersize = PAPER_DEFAULT;
412 orientation = ORIENTATION_PORTRAIT;
413 use_geometry = false;
414 biblio_style = "plain";
415 use_bibtopic = false;
417 save_transient_properties = true;
418 track_changes = false;
419 output_changes = false;
420 use_default_options = true;
421 maintain_unincluded_children = false;
424 language = default_language;
426 fonts_roman[0] = "default";
427 fonts_roman[1] = "default";
428 fonts_sans[0] = "default";
429 fonts_sans[1] = "default";
430 fonts_typewriter[0] = "default";
431 fonts_typewriter[1] = "default";
432 fonts_math[0] = "auto";
433 fonts_math[1] = "auto";
434 fonts_default_family = "default";
435 useNonTeXFonts = false;
436 use_microtype = false;
437 fonts_expert_sc = false;
438 fonts_old_figures = false;
439 fonts_sans_scale[0] = 100;
440 fonts_sans_scale[1] = 100;
441 fonts_typewriter_scale[0] = 100;
442 fonts_typewriter_scale[1] = 100;
444 lang_package = "default";
445 graphics_driver = "default";
446 default_output_format = "default";
447 bibtex_command = "default";
448 index_command = "default";
451 listings_params = string();
452 pagestyle = "default";
453 suppress_date = false;
454 justification = true;
455 // no color is the default (white)
456 backgroundcolor = lyx::rgbFromHexName("#ffffff");
457 isbackgroundcolor = false;
458 // no color is the default (black)
459 fontcolor = lyx::rgbFromHexName("#000000");
461 // light gray is the default font color for greyed-out notes
462 notefontcolor = lyx::rgbFromHexName("#cccccc");
463 boxbgcolor = lyx::rgbFromHexName("#ff0000");
464 compressed = lyxrc.save_compressed;
465 for (int iter = 0; iter < 4; ++iter) {
466 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
467 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
470 indiceslist().addDefault(B_("Index"));
471 html_be_strict = false;
472 html_math_output = MathML;
473 html_math_img_scale = 1.0;
474 html_css_as_file = false;
475 display_pixel_ratio = 1.0;
480 // map current author
481 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
485 docstring BufferParams::B_(string const & l10n) const
487 LASSERT(language, return from_utf8(l10n));
488 return getMessages(language->code()).get(l10n);
492 BufferParams::Package BufferParams::use_package(std::string const & p) const
494 PackageMap::const_iterator it = use_packages.find(p);
495 if (it == use_packages.end())
501 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
507 map<string, string> const & BufferParams::auto_packages()
509 static map<string, string> packages;
510 if (packages.empty()) {
511 // We could have a race condition here that two threads
512 // discover an empty map at the same time and want to fill
513 // it, but that is no problem, since the same contents is
514 // filled in twice then. Having the locker inside the
515 // packages.empty() condition has the advantage that we
516 // don't need the mutex overhead for simple reading.
518 Mutex::Locker locker(&mutex);
519 // adding a package here implies a file format change!
520 packages["amsmath"] =
521 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
522 packages["amssymb"] =
523 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
525 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
527 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
528 packages["mathdots"] =
529 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
530 packages["mathtools"] =
531 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
533 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
534 packages["stackrel"] =
535 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
536 packages["stmaryrd"] =
537 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");
538 packages["undertilde"] =
539 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
545 AuthorList & BufferParams::authors()
547 return pimpl_->authorlist;
551 AuthorList const & BufferParams::authors() const
553 return pimpl_->authorlist;
557 void BufferParams::addAuthor(Author a)
559 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
563 BranchList & BufferParams::branchlist()
565 return pimpl_->branchlist;
569 BranchList const & BufferParams::branchlist() const
571 return pimpl_->branchlist;
575 IndicesList & BufferParams::indiceslist()
577 return pimpl_->indiceslist;
581 IndicesList const & BufferParams::indiceslist() const
583 return pimpl_->indiceslist;
587 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
589 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
590 return pimpl_->temp_bullets[index];
594 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
596 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
597 return pimpl_->temp_bullets[index];
601 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
603 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
604 return pimpl_->user_defined_bullets[index];
608 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
610 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
611 return pimpl_->user_defined_bullets[index];
615 Spacing & BufferParams::spacing()
617 return pimpl_->spacing;
621 Spacing const & BufferParams::spacing() const
623 return pimpl_->spacing;
627 PDFOptions & BufferParams::pdfoptions()
629 return pimpl_->pdfoptions;
633 PDFOptions const & BufferParams::pdfoptions() const
635 return pimpl_->pdfoptions;
639 HSpace const & BufferParams::getIndentation() const
641 return pimpl_->indentation;
645 void BufferParams::setIndentation(HSpace const & indent)
647 pimpl_->indentation = indent;
651 VSpace const & BufferParams::getDefSkip() const
653 return pimpl_->defskip;
657 void BufferParams::setDefSkip(VSpace const & vs)
659 // DEFSKIP will cause an infinite loop
660 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
661 pimpl_->defskip = vs;
665 string BufferParams::readToken(Lexer & lex, string const & token,
666 FileName const & filepath)
670 if (token == "\\textclass") {
672 string const classname = lex.getString();
673 // if there exists a local layout file, ignore the system one
674 // NOTE: in this case, the textclass (.cls file) is assumed to
677 LayoutFileList & bcl = LayoutFileList::get();
678 if (!filepath.empty()) {
679 // If classname is an absolute path, the document is
680 // using a local layout file which could not be accessed
681 // by a relative path. In this case the path is correct
682 // even if the document was moved to a different
683 // location. However, we will have a problem if the
684 // document was generated on a different platform.
685 bool isabsolute = FileName::isAbsolute(classname);
686 string const classpath = onlyPath(classname);
687 string const path = isabsolute ? classpath
688 : FileName(addPath(filepath.absFileName(),
689 classpath)).realPath();
690 string const oldpath = isabsolute ? string()
691 : FileName(addPath(origin, classpath)).realPath();
692 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
694 // that returns non-empty if a "local" layout file is found.
696 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
697 from_utf8(filepath.absFileName())));
700 setBaseClass(onlyFileName(tcp));
702 setBaseClass(onlyFileName(classname));
703 // We assume that a tex class exists for local or unknown
704 // layouts so this warning, will only be given for system layouts.
705 if (!baseClass()->isTeXClassAvailable()) {
706 docstring const desc =
707 translateIfPossible(from_utf8(baseClass()->description()));
708 docstring const prereqs =
709 from_utf8(baseClass()->prerequisites());
710 docstring const msg =
711 bformat(_("The selected document class\n"
713 "requires external files that are not available.\n"
714 "The document class can still be used, but the\n"
715 "document cannot be compiled until the following\n"
716 "prerequisites are installed:\n"
718 "See section 3.1.2.2 (Class Availability) of the\n"
719 "User's Guide for more information."), desc, prereqs);
720 frontend::Alert::warning(_("Document class not available"),
723 } else if (token == "\\save_transient_properties") {
724 lex >> save_transient_properties;
725 } else if (token == "\\origin") {
727 origin = lex.getString();
728 string const sysdirprefix = "/systemlyxdir/";
729 if (prefixIs(origin, sysdirprefix)) {
731 if (inSystemDir(filepath, docsys))
732 origin.replace(0, sysdirprefix.length() - 1, docsys);
734 origin.replace(0, sysdirprefix.length() - 1,
735 package().system_support().absFileName());
737 } else if (token == "\\begin_preamble") {
739 } else if (token == "\\begin_local_layout") {
740 readLocalLayout(lex, false);
741 } else if (token == "\\begin_forced_local_layout") {
742 readLocalLayout(lex, true);
743 } else if (token == "\\begin_modules") {
745 } else if (token == "\\begin_removed_modules") {
746 readRemovedModules(lex);
747 } else if (token == "\\begin_includeonly") {
748 readIncludeonly(lex);
749 } else if (token == "\\maintain_unincluded_children") {
750 lex >> maintain_unincluded_children;
751 } else if (token == "\\options") {
753 options = lex.getString();
754 } else if (token == "\\use_default_options") {
755 lex >> use_default_options;
756 } else if (token == "\\master") {
758 master = lex.getString();
759 if (!filepath.empty() && FileName::isAbsolute(origin)) {
760 bool const isabs = FileName::isAbsolute(master);
761 FileName const abspath(isabs ? master : origin + master);
762 bool const moved = filepath != FileName(origin);
763 if (moved && abspath.exists()) {
764 docstring const path = isabs
766 : from_utf8(abspath.realPath());
767 docstring const refpath =
768 from_utf8(filepath.absFileName());
769 master = to_utf8(makeRelPath(path, refpath));
772 } else if (token == "\\suppress_date") {
773 lex >> suppress_date;
774 } else if (token == "\\justification") {
775 lex >> justification;
776 } else if (token == "\\language") {
778 } else if (token == "\\language_package") {
780 lang_package = lex.getString();
781 } else if (token == "\\inputencoding") {
783 } else if (token == "\\graphics") {
784 readGraphicsDriver(lex);
785 } else if (token == "\\default_output_format") {
786 lex >> default_output_format;
787 } else if (token == "\\bibtex_command") {
789 bibtex_command = lex.getString();
790 } else if (token == "\\index_command") {
792 index_command = lex.getString();
793 } else if (token == "\\fontencoding") {
795 fontenc = lex.getString();
796 } else if (token == "\\font_roman") {
797 lex >> fonts_roman[0];
798 lex >> fonts_roman[1];
799 } else if (token == "\\font_sans") {
800 lex >> fonts_sans[0];
801 lex >> fonts_sans[1];
802 } else if (token == "\\font_typewriter") {
803 lex >> fonts_typewriter[0];
804 lex >> fonts_typewriter[1];
805 } else if (token == "\\font_math") {
806 lex >> fonts_math[0];
807 lex >> fonts_math[1];
808 } else if (token == "\\font_default_family") {
809 lex >> fonts_default_family;
810 } else if (token == "\\use_non_tex_fonts") {
811 lex >> useNonTeXFonts;
812 } else if (token == "\\font_sc") {
813 lex >> fonts_expert_sc;
814 } else if (token == "\\font_osf") {
815 lex >> fonts_old_figures;
816 } else if (token == "\\font_sf_scale") {
817 lex >> fonts_sans_scale[0];
818 lex >> fonts_sans_scale[1];
819 } else if (token == "\\font_tt_scale") {
820 lex >> fonts_typewriter_scale[0];
821 lex >> fonts_typewriter_scale[1];
822 } else if (token == "\\font_cjk") {
824 } else if (token == "\\use_microtype") {
825 lex >> use_microtype;
826 } else if (token == "\\paragraph_separation") {
829 paragraph_separation = parseptranslator().find(parsep);
830 } else if (token == "\\paragraph_indentation") {
832 string indentation = lex.getString();
833 pimpl_->indentation = HSpace(indentation);
834 } else if (token == "\\defskip") {
836 string const defskip = lex.getString();
837 pimpl_->defskip = VSpace(defskip);
838 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
840 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
841 } else if (token == "\\quotes_style") {
844 quotes_style = quotesstyletranslator().find(qstyle);
845 } else if (token == "\\dynamic_quotes") {
846 lex >> dynamic_quotes;
847 } else if (token == "\\papersize") {
850 papersize = papersizetranslator().find(ppsize);
851 } else if (token == "\\use_geometry") {
853 } else if (token == "\\use_package") {
858 use_package(package, packagetranslator().find(use));
859 } else if (token == "\\cite_engine") {
861 vector<string> engine = getVectorFromString(lex.getString());
862 setCiteEngine(engine);
863 } else if (token == "\\cite_engine_type") {
866 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
867 } else if (token == "\\biblio_style") {
869 biblio_style = lex.getString();
870 } else if (token == "\\use_bibtopic") {
872 } else if (token == "\\use_indices") {
874 } else if (token == "\\tracking_changes") {
875 lex >> track_changes;
876 } else if (token == "\\output_changes") {
877 lex >> output_changes;
878 } else if (token == "\\branch") {
880 docstring branch = lex.getDocString();
881 branchlist().add(branch);
884 string const tok = lex.getString();
885 if (tok == "\\end_branch")
887 Branch * branch_ptr = branchlist().find(branch);
888 if (tok == "\\selected") {
891 branch_ptr->setSelected(lex.getInteger());
893 if (tok == "\\filename_suffix") {
896 branch_ptr->setFileNameSuffix(lex.getInteger());
898 if (tok == "\\color") {
900 string color = lex.getString();
902 branch_ptr->setColor(color);
903 // Update also the Color table:
905 color = lcolor.getX11Name(Color_background);
907 lcolor.setColor(to_utf8(branch), color);
910 } else if (token == "\\index") {
912 docstring index = lex.getDocString();
914 indiceslist().add(index);
917 string const tok = lex.getString();
918 if (tok == "\\end_index")
920 Index * index_ptr = indiceslist().find(index);
921 if (tok == "\\shortcut") {
923 shortcut = lex.getDocString();
925 index_ptr->setShortcut(shortcut);
927 if (tok == "\\color") {
929 string color = lex.getString();
931 index_ptr->setColor(color);
932 // Update also the Color table:
934 color = lcolor.getX11Name(Color_background);
936 if (!shortcut.empty())
937 lcolor.setColor(to_utf8(shortcut), color);
940 } else if (token == "\\author") {
942 istringstream ss(lex.getString());
946 } else if (token == "\\paperorientation") {
949 orientation = paperorientationtranslator().find(orient);
950 } else if (token == "\\backgroundcolor") {
952 backgroundcolor = lyx::rgbFromHexName(lex.getString());
953 isbackgroundcolor = true;
954 } else if (token == "\\fontcolor") {
956 fontcolor = lyx::rgbFromHexName(lex.getString());
958 } else if (token == "\\notefontcolor") {
960 string color = lex.getString();
961 notefontcolor = lyx::rgbFromHexName(color);
962 lcolor.setColor("notefontcolor", color);
963 } else if (token == "\\boxbgcolor") {
965 string color = lex.getString();
966 boxbgcolor = lyx::rgbFromHexName(color);
967 lcolor.setColor("boxbgcolor", color);
968 } else if (token == "\\paperwidth") {
970 } else if (token == "\\paperheight") {
972 } else if (token == "\\leftmargin") {
974 } else if (token == "\\topmargin") {
976 } else if (token == "\\rightmargin") {
978 } else if (token == "\\bottommargin") {
980 } else if (token == "\\headheight") {
982 } else if (token == "\\headsep") {
984 } else if (token == "\\footskip") {
986 } else if (token == "\\columnsep") {
988 } else if (token == "\\paperfontsize") {
990 } else if (token == "\\papercolumns") {
992 } else if (token == "\\listings_params") {
995 listings_params = InsetListingsParams(par).params();
996 } else if (token == "\\papersides") {
999 sides = sidestranslator().find(psides);
1000 } else if (token == "\\paperpagestyle") {
1002 } else if (token == "\\bullet") {
1004 } else if (token == "\\bulletLaTeX") {
1005 readBulletsLaTeX(lex);
1006 } else if (token == "\\secnumdepth") {
1008 } else if (token == "\\tocdepth") {
1010 } else if (token == "\\spacing") {
1014 if (nspacing == "other") {
1017 spacing().set(spacetranslator().find(nspacing), tmp_val);
1018 } else if (token == "\\float_placement") {
1019 lex >> float_placement;
1021 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
1022 string toktmp = pdfoptions().readToken(lex, token);
1023 if (!toktmp.empty()) {
1024 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
1028 } else if (token == "\\html_math_output") {
1031 html_math_output = static_cast<MathOutput>(temp);
1032 } else if (token == "\\html_be_strict") {
1033 lex >> html_be_strict;
1034 } else if (token == "\\html_css_as_file") {
1035 lex >> html_css_as_file;
1036 } else if (token == "\\html_math_img_scale") {
1037 lex >> html_math_img_scale;
1038 } else if (token == "\\html_latex_start") {
1040 html_latex_start = lex.getString();
1041 } else if (token == "\\html_latex_end") {
1043 html_latex_end = lex.getString();
1044 } else if (token == "\\output_sync") {
1046 } else if (token == "\\output_sync_macro") {
1047 lex >> output_sync_macro;
1048 } else if (token == "\\use_refstyle") {
1049 lex >> use_refstyle;
1051 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1061 // Quote argument if it contains spaces
1062 string quoteIfNeeded(string const & str) {
1063 if (contains(str, ' '))
1064 return "\"" + str + "\"";
1070 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1072 // The top of the file is written by the buffer.
1073 // Prints out the buffer info into the .lyx file given by file
1075 os << "\\save_transient_properties "
1076 << convert<string>(save_transient_properties) << '\n';
1078 // the document directory (must end with a path separator)
1079 // realPath() is used to resolve symlinks, while addPath(..., "")
1080 // ensures a trailing path separator.
1082 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1083 string const sysdir = inSystemDir(FileName(filepath), docsys) ? docsys
1084 : addPath(package().system_support().realPath(), "");
1085 string const relpath =
1086 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1087 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1088 filepath = addPath("/systemlyxdir", relpath);
1089 else if (!save_transient_properties || !lyxrc.save_origin)
1090 filepath = "unavailable";
1091 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1094 os << "\\textclass "
1095 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1096 baseClass()->name()), "layout"))
1099 // then the preamble
1100 if (!preamble.empty()) {
1101 // remove '\n' from the end of preamble
1102 docstring const tmppreamble = rtrim(preamble, "\n");
1103 os << "\\begin_preamble\n"
1104 << to_utf8(tmppreamble)
1105 << "\n\\end_preamble\n";
1109 if (!options.empty()) {
1110 os << "\\options " << options << '\n';
1113 // use the class options defined in the layout?
1114 os << "\\use_default_options "
1115 << convert<string>(use_default_options) << "\n";
1117 // the master document
1118 if (!master.empty()) {
1119 os << "\\master " << master << '\n';
1123 if (!removed_modules_.empty()) {
1124 os << "\\begin_removed_modules" << '\n';
1125 list<string>::const_iterator it = removed_modules_.begin();
1126 list<string>::const_iterator en = removed_modules_.end();
1127 for (; it != en; ++it)
1129 os << "\\end_removed_modules" << '\n';
1133 if (!layout_modules_.empty()) {
1134 os << "\\begin_modules" << '\n';
1135 LayoutModuleList::const_iterator it = layout_modules_.begin();
1136 LayoutModuleList::const_iterator en = layout_modules_.end();
1137 for (; it != en; ++it)
1139 os << "\\end_modules" << '\n';
1143 if (!included_children_.empty()) {
1144 os << "\\begin_includeonly" << '\n';
1145 list<string>::const_iterator it = included_children_.begin();
1146 list<string>::const_iterator en = included_children_.end();
1147 for (; it != en; ++it)
1149 os << "\\end_includeonly" << '\n';
1151 os << "\\maintain_unincluded_children "
1152 << convert<string>(maintain_unincluded_children) << '\n';
1154 // local layout information
1155 docstring const local_layout = getLocalLayout(false);
1156 if (!local_layout.empty()) {
1157 // remove '\n' from the end
1158 docstring const tmplocal = rtrim(local_layout, "\n");
1159 os << "\\begin_local_layout\n"
1160 << to_utf8(tmplocal)
1161 << "\n\\end_local_layout\n";
1163 docstring const forced_local_layout = getLocalLayout(true);
1164 if (!forced_local_layout.empty()) {
1165 // remove '\n' from the end
1166 docstring const tmplocal = rtrim(forced_local_layout, "\n");
1167 os << "\\begin_forced_local_layout\n"
1168 << to_utf8(tmplocal)
1169 << "\n\\end_forced_local_layout\n";
1172 // then the text parameters
1173 if (language != ignore_language)
1174 os << "\\language " << language->lang() << '\n';
1175 os << "\\language_package " << lang_package
1176 << "\n\\inputencoding " << inputenc
1177 << "\n\\fontencoding " << fontenc
1178 << "\n\\font_roman \"" << fonts_roman[0]
1179 << "\" \"" << fonts_roman[1] << '"'
1180 << "\n\\font_sans \"" << fonts_sans[0]
1181 << "\" \"" << fonts_sans[1] << '"'
1182 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1183 << "\" \"" << fonts_typewriter[1] << '"'
1184 << "\n\\font_math \"" << fonts_math[0]
1185 << "\" \"" << fonts_math[1] << '"'
1186 << "\n\\font_default_family " << fonts_default_family
1187 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1188 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1189 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1190 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1191 << ' ' << fonts_sans_scale[1]
1192 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1193 << ' ' << fonts_typewriter_scale[1]
1195 if (!fonts_cjk.empty()) {
1196 os << "\\font_cjk " << fonts_cjk << '\n';
1198 os << "\\use_microtype " << convert<string>(use_microtype) << '\n';
1199 os << "\\graphics " << graphics_driver << '\n';
1200 os << "\\default_output_format " << default_output_format << '\n';
1201 os << "\\output_sync " << output_sync << '\n';
1202 if (!output_sync_macro.empty())
1203 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1204 os << "\\bibtex_command " << bibtex_command << '\n';
1205 os << "\\index_command " << index_command << '\n';
1207 if (!float_placement.empty()) {
1208 os << "\\float_placement " << float_placement << '\n';
1210 os << "\\paperfontsize " << fontsize << '\n';
1212 spacing().writeFile(os);
1213 pdfoptions().writeFile(os);
1215 os << "\\papersize " << string_papersize[papersize]
1216 << "\n\\use_geometry " << convert<string>(use_geometry);
1217 map<string, string> const & packages = auto_packages();
1218 for (map<string, string>::const_iterator it = packages.begin();
1219 it != packages.end(); ++it)
1220 os << "\n\\use_package " << it->first << ' '
1221 << use_package(it->first);
1223 os << "\n\\cite_engine ";
1225 if (!cite_engine_.empty()) {
1226 LayoutModuleList::const_iterator be = cite_engine_.begin();
1227 LayoutModuleList::const_iterator en = cite_engine_.end();
1228 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1237 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1238 << "\n\\biblio_style " << biblio_style
1239 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1240 << "\n\\use_indices " << convert<string>(use_indices)
1241 << "\n\\paperorientation " << string_orientation[orientation]
1242 << "\n\\suppress_date " << convert<string>(suppress_date)
1243 << "\n\\justification " << convert<string>(justification)
1244 << "\n\\use_refstyle " << use_refstyle
1246 if (isbackgroundcolor == true)
1247 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1248 if (isfontcolor == true)
1249 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1250 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1251 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1252 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1253 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1255 BranchList::const_iterator it = branchlist().begin();
1256 BranchList::const_iterator end = branchlist().end();
1257 for (; it != end; ++it) {
1258 os << "\\branch " << to_utf8(it->branch())
1259 << "\n\\selected " << it->isSelected()
1260 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1261 << "\n\\color " << lyx::X11hexname(it->color())
1266 IndicesList::const_iterator iit = indiceslist().begin();
1267 IndicesList::const_iterator iend = indiceslist().end();
1268 for (; iit != iend; ++iit) {
1269 os << "\\index " << to_utf8(iit->index())
1270 << "\n\\shortcut " << to_utf8(iit->shortcut())
1271 << "\n\\color " << lyx::X11hexname(iit->color())
1276 if (!paperwidth.empty())
1277 os << "\\paperwidth "
1278 << VSpace(paperwidth).asLyXCommand() << '\n';
1279 if (!paperheight.empty())
1280 os << "\\paperheight "
1281 << VSpace(paperheight).asLyXCommand() << '\n';
1282 if (!leftmargin.empty())
1283 os << "\\leftmargin "
1284 << VSpace(leftmargin).asLyXCommand() << '\n';
1285 if (!topmargin.empty())
1286 os << "\\topmargin "
1287 << VSpace(topmargin).asLyXCommand() << '\n';
1288 if (!rightmargin.empty())
1289 os << "\\rightmargin "
1290 << VSpace(rightmargin).asLyXCommand() << '\n';
1291 if (!bottommargin.empty())
1292 os << "\\bottommargin "
1293 << VSpace(bottommargin).asLyXCommand() << '\n';
1294 if (!headheight.empty())
1295 os << "\\headheight "
1296 << VSpace(headheight).asLyXCommand() << '\n';
1297 if (!headsep.empty())
1299 << VSpace(headsep).asLyXCommand() << '\n';
1300 if (!footskip.empty())
1302 << VSpace(footskip).asLyXCommand() << '\n';
1303 if (!columnsep.empty())
1304 os << "\\columnsep "
1305 << VSpace(columnsep).asLyXCommand() << '\n';
1306 os << "\\secnumdepth " << secnumdepth
1307 << "\n\\tocdepth " << tocdepth
1308 << "\n\\paragraph_separation "
1309 << string_paragraph_separation[paragraph_separation];
1310 if (!paragraph_separation)
1311 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1313 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1314 os << "\n\\quotes_style "
1315 << string_quotes_style[quotes_style]
1316 << "\n\\dynamic_quotes " << dynamic_quotes
1317 << "\n\\papercolumns " << columns
1318 << "\n\\papersides " << sides
1319 << "\n\\paperpagestyle " << pagestyle << '\n';
1320 if (!listings_params.empty())
1321 os << "\\listings_params \"" <<
1322 InsetListingsParams(listings_params).encodedString() << "\"\n";
1323 for (int i = 0; i < 4; ++i) {
1324 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1325 if (user_defined_bullet(i).getFont() != -1) {
1326 os << "\\bullet " << i << " "
1327 << user_defined_bullet(i).getFont() << " "
1328 << user_defined_bullet(i).getCharacter() << " "
1329 << user_defined_bullet(i).getSize() << "\n";
1333 os << "\\bulletLaTeX " << i << " \""
1334 << lyx::to_ascii(user_defined_bullet(i).getText())
1340 os << "\\tracking_changes "
1341 << (save_transient_properties ? convert<string>(track_changes) : "false")
1344 os << "\\output_changes "
1345 << (save_transient_properties ? convert<string>(output_changes) : "false")
1348 os << "\\html_math_output " << html_math_output << '\n'
1349 << "\\html_css_as_file " << html_css_as_file << '\n'
1350 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1352 if (html_math_img_scale != 1.0)
1353 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1354 if (!html_latex_start.empty())
1355 os << "\\html_latex_start " << html_latex_start << '\n';
1356 if (!html_latex_end.empty())
1357 os << "\\html_latex_end " << html_latex_end << '\n';
1359 os << pimpl_->authorlist;
1363 void BufferParams::validate(LaTeXFeatures & features) const
1365 features.require(documentClass().requires());
1367 if (columns > 1 && language->rightToLeft())
1368 features.require("rtloutputdblcol");
1370 if (output_changes) {
1371 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1372 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1373 LaTeXFeatures::isAvailable("xcolor");
1375 switch (features.runparams().flavor) {
1376 case OutputParams::LATEX:
1377 case OutputParams::DVILUATEX:
1379 features.require("ct-dvipost");
1380 features.require("dvipost");
1381 } else if (xcolorulem) {
1382 features.require("ct-xcolor-ulem");
1383 features.require("ulem");
1384 features.require("xcolor");
1386 features.require("ct-none");
1389 case OutputParams::LUATEX:
1390 case OutputParams::PDFLATEX:
1391 case OutputParams::XETEX:
1393 features.require("ct-xcolor-ulem");
1394 features.require("ulem");
1395 features.require("xcolor");
1396 // improves color handling in PDF output
1397 features.require("pdfcolmk");
1399 features.require("ct-none");
1407 // Floats with 'Here definitely' as default setting.
1408 if (float_placement.find('H') != string::npos)
1409 features.require("float");
1411 for (PackageMap::const_iterator it = use_packages.begin();
1412 it != use_packages.end(); ++it) {
1413 if (it->first == "amsmath") {
1414 // AMS Style is at document level
1415 if (it->second == package_on ||
1416 features.isProvided("amsmath"))
1417 features.require(it->first);
1418 } else if (it->second == package_on)
1419 features.require(it->first);
1422 // Document-level line spacing
1423 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1424 features.require("setspace");
1426 // the bullet shapes are buffer level not paragraph level
1427 // so they are tested here
1428 for (int i = 0; i < 4; ++i) {
1429 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1431 int const font = user_defined_bullet(i).getFont();
1433 int const c = user_defined_bullet(i).getCharacter();
1439 features.require("latexsym");
1441 } else if (font == 1) {
1442 features.require("amssymb");
1443 } else if (font >= 2 && font <= 5) {
1444 features.require("pifont");
1448 if (pdfoptions().use_hyperref) {
1449 features.require("hyperref");
1450 // due to interferences with babel and hyperref, the color package has to
1451 // be loaded after hyperref when hyperref is used with the colorlinks
1452 // option, see http://www.lyx.org/trac/ticket/5291
1453 if (pdfoptions().colorlinks)
1454 features.require("color");
1456 if (!listings_params.empty()) {
1457 // do not test validity because listings_params is
1458 // supposed to be valid
1460 InsetListingsParams(listings_params).separatedParams(true);
1461 // we can't support all packages, but we should load the color package
1462 if (par.find("\\color", 0) != string::npos)
1463 features.require("color");
1466 // some languages are only available via polyglossia
1467 if (features.hasPolyglossiaExclusiveLanguages())
1468 features.require("polyglossia");
1470 if (useNonTeXFonts && fontsMath() != "auto")
1471 features.require("unicode-math");
1474 features.require("microtype");
1476 if (!language->requires().empty())
1477 features.require(language->requires());
1481 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1482 FileName const & filepath) const
1484 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1485 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1486 // \RequirePackage to do so, rather than the normal \usepackage
1487 // Do not try to load any other package before the document class, unless you
1488 // have a thorough understanding of the LATEX internals and know exactly what you
1490 if (features.mustProvide("fix-cm"))
1491 os << "\\RequirePackage{fix-cm}\n";
1492 // Likewise for fixltx2e. If other packages conflict with this policy,
1493 // treat it as a package bug (and report it!)
1494 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1495 if (features.mustProvide("fixltx2e"))
1496 os << "\\RequirePackage{fixltx2e}\n";
1498 os << "\\documentclass";
1500 DocumentClass const & tclass = documentClass();
1502 ostringstream clsoptions; // the document class options.
1504 if (tokenPos(tclass.opt_fontsize(),
1505 '|', fontsize) >= 0) {
1506 // only write if existing in list (and not default)
1507 clsoptions << fontsize << "pt,";
1510 // all paper sizes except of A4, A5, B5 and the US sizes need the
1512 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1513 && papersize != PAPER_USLETTER
1514 && papersize != PAPER_USLEGAL
1515 && papersize != PAPER_USEXECUTIVE
1516 && papersize != PAPER_A4
1517 && papersize != PAPER_A5
1518 && papersize != PAPER_B5;
1520 if (!use_geometry) {
1521 switch (papersize) {
1523 clsoptions << "a4paper,";
1525 case PAPER_USLETTER:
1526 clsoptions << "letterpaper,";
1529 clsoptions << "a5paper,";
1532 clsoptions << "b5paper,";
1534 case PAPER_USEXECUTIVE:
1535 clsoptions << "executivepaper,";
1538 clsoptions << "legalpaper,";
1572 if (sides != tclass.sides()) {
1575 clsoptions << "oneside,";
1578 clsoptions << "twoside,";
1584 if (columns != tclass.columns()) {
1586 clsoptions << "twocolumn,";
1588 clsoptions << "onecolumn,";
1592 && orientation == ORIENTATION_LANDSCAPE)
1593 clsoptions << "landscape,";
1595 // language should be a parameter to \documentclass
1596 if (language->babel() == "hebrew"
1597 && default_language->babel() != "hebrew")
1598 // This seems necessary
1599 features.useLanguage(default_language);
1601 ostringstream language_options;
1602 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1603 bool const use_polyglossia = features.usePolyglossia();
1604 bool const global = lyxrc.language_global_options;
1605 if (use_babel || (use_polyglossia && global)) {
1606 language_options << features.getBabelLanguages();
1607 if (!language->babel().empty()) {
1608 if (!language_options.str().empty())
1609 language_options << ',';
1610 language_options << language->babel();
1612 if (global && !features.needBabelLangOptions()
1613 && !language_options.str().empty())
1614 clsoptions << language_options.str() << ',';
1617 // the predefined options from the layout
1618 if (use_default_options && !tclass.options().empty())
1619 clsoptions << tclass.options() << ',';
1621 // the user-defined options
1622 if (!options.empty()) {
1623 clsoptions << options << ',';
1626 string strOptions(clsoptions.str());
1627 if (!strOptions.empty()) {
1628 strOptions = rtrim(strOptions, ",");
1630 os << '[' << from_utf8(strOptions) << ']';
1633 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1634 // end of \documentclass defs
1636 // if we use fontspec or newtxmath, we have to load the AMS packages here
1637 string const ams = features.loadAMSPackages();
1638 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1639 bool const use_newtxmath =
1640 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1641 ot1, false, false) == "newtxmath";
1642 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1643 os << from_ascii(ams);
1645 if (useNonTeXFonts) {
1646 if (!features.isProvided("fontspec"))
1647 os << "\\usepackage{fontspec}\n";
1648 if (features.mustProvide("unicode-math")
1649 && features.isAvailable("unicode-math"))
1650 os << "\\usepackage{unicode-math}\n";
1653 // font selection must be done before loading fontenc.sty
1654 string const fonts = loadFonts(features);
1656 os << from_utf8(fonts);
1658 if (fonts_default_family != "default")
1659 os << "\\renewcommand{\\familydefault}{\\"
1660 << from_ascii(fonts_default_family) << "}\n";
1662 // set font encoding
1663 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1664 if (!useNonTeXFonts && !features.isProvided("fontenc")
1665 && font_encoding() != "default") {
1666 // get main font encodings
1667 vector<string> fontencs = font_encodings();
1668 // get font encodings of secondary languages
1669 features.getFontEncodings(fontencs);
1670 if (!fontencs.empty()) {
1671 os << "\\usepackage["
1672 << from_ascii(getStringFromVector(fontencs))
1677 // handle inputenc etc.
1678 writeEncodingPreamble(os, features);
1681 if (!features.runparams().includeall && !included_children_.empty()) {
1682 os << "\\includeonly{";
1683 list<string>::const_iterator it = included_children_.begin();
1684 list<string>::const_iterator en = included_children_.end();
1686 for (; it != en; ++it) {
1687 string incfile = *it;
1688 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1689 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1691 if (!features.runparams().nice)
1693 // \includeonly doesn't want an extension
1694 incfile = changeExtension(incfile, string());
1695 incfile = support::latex_path(incfile);
1696 if (!incfile.empty()) {
1699 os << from_utf8(incfile);
1706 if (!features.isProvided("geometry")
1707 && (use_geometry || nonstandard_papersize)) {
1708 odocstringstream ods;
1709 if (!getGraphicsDriver("geometry").empty())
1710 ods << getGraphicsDriver("geometry");
1711 if (orientation == ORIENTATION_LANDSCAPE)
1712 ods << ",landscape";
1713 switch (papersize) {
1715 if (!paperwidth.empty())
1716 ods << ",paperwidth="
1717 << from_ascii(paperwidth);
1718 if (!paperheight.empty())
1719 ods << ",paperheight="
1720 << from_ascii(paperheight);
1722 case PAPER_USLETTER:
1723 ods << ",letterpaper";
1726 ods << ",legalpaper";
1728 case PAPER_USEXECUTIVE:
1729 ods << ",executivepaper";
1818 docstring const g_options = trim(ods.str(), ",");
1819 os << "\\usepackage";
1820 if (!g_options.empty())
1821 os << '[' << g_options << ']';
1822 os << "{geometry}\n";
1823 // output this only if use_geometry is true
1825 os << "\\geometry{verbose";
1826 if (!topmargin.empty())
1827 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1828 if (!bottommargin.empty())
1829 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1830 if (!leftmargin.empty())
1831 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1832 if (!rightmargin.empty())
1833 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1834 if (!headheight.empty())
1835 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1836 if (!headsep.empty())
1837 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1838 if (!footskip.empty())
1839 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1840 if (!columnsep.empty())
1841 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1844 } else if (orientation == ORIENTATION_LANDSCAPE
1845 || papersize != PAPER_DEFAULT) {
1846 features.require("papersize");
1849 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1850 if (pagestyle == "fancy")
1851 os << "\\usepackage{fancyhdr}\n";
1852 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1855 // only output when the background color is not default
1856 if (isbackgroundcolor == true) {
1857 // only require color here, the background color will be defined
1858 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1860 features.require("color");
1861 features.require("pagecolor");
1864 // only output when the font color is not default
1865 if (isfontcolor == true) {
1866 // only require color here, the font color will be defined
1867 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1869 features.require("color");
1870 features.require("fontcolor");
1873 // Only if class has a ToC hierarchy
1874 if (tclass.hasTocLevels()) {
1875 if (secnumdepth != tclass.secnumdepth()) {
1876 os << "\\setcounter{secnumdepth}{"
1880 if (tocdepth != tclass.tocdepth()) {
1881 os << "\\setcounter{tocdepth}{"
1887 if (paragraph_separation) {
1888 // when skip separation
1889 switch (getDefSkip().kind()) {
1890 case VSpace::SMALLSKIP:
1891 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1893 case VSpace::MEDSKIP:
1894 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1896 case VSpace::BIGSKIP:
1897 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1899 case VSpace::LENGTH:
1900 os << "\\setlength{\\parskip}{"
1901 << from_utf8(getDefSkip().length().asLatexString())
1904 default: // should never happen // Then delete it.
1905 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1908 os << "\\setlength{\\parindent}{0pt}\n";
1910 // when separation by indentation
1911 // only output something when a width is given
1912 if (getIndentation().asLyXCommand() != "default") {
1913 os << "\\setlength{\\parindent}{"
1914 << from_utf8(getIndentation().asLatexCommand())
1919 // Now insert the LyX specific LaTeX commands...
1920 features.resolveAlternatives();
1921 features.expandMultiples();
1924 if (!output_sync_macro.empty())
1925 os << from_utf8(output_sync_macro) +"\n";
1926 else if (features.runparams().flavor == OutputParams::LATEX)
1927 os << "\\usepackage[active]{srcltx}\n";
1928 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1929 os << "\\synctex=-1\n";
1932 // The package options (via \PassOptionsToPackage)
1933 os << from_ascii(features.getPackageOptions());
1935 // due to interferences with babel and hyperref, the color package has to
1936 // be loaded (when it is not already loaded) before babel when hyperref
1937 // is used with the colorlinks option, see
1938 // http://www.lyx.org/trac/ticket/5291
1939 // we decided therefore to load color always before babel, see
1940 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1941 os << from_ascii(features.getColorOptions());
1943 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1944 // we have to call babel before
1946 && (features.isRequired("jurabib")
1947 || features.isRequired("hyperref")
1948 || features.isRequired("varioref")
1949 || features.isRequired("vietnamese")
1950 || features.isRequired("japanese"))) {
1951 os << features.getBabelPresettings();
1953 os << from_utf8(babelCall(language_options.str(),
1954 features.needBabelLangOptions())) + '\n';
1955 os << features.getBabelPostsettings();
1958 // The optional packages;
1959 os << from_ascii(features.getPackages());
1961 // Additional Indices
1962 if (features.isRequired("splitidx")) {
1963 IndicesList::const_iterator iit = indiceslist().begin();
1964 IndicesList::const_iterator iend = indiceslist().end();
1965 for (; iit != iend; ++iit) {
1966 pair<docstring, docstring> indexname_latex =
1967 features.runparams().encoding->latexString(iit->index(),
1968 features.runparams().dryrun);
1969 if (!indexname_latex.second.empty()) {
1970 // issue a warning about omitted characters
1971 // FIXME: should be passed to the error dialog
1972 frontend::Alert::warning(_("Uncodable characters"),
1973 bformat(_("The following characters that are used in an index name are not\n"
1974 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1975 indexname_latex.second));
1977 os << "\\newindex[";
1978 os << indexname_latex.first;
1980 os << escape(iit->shortcut());
1986 os << from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1989 // * Hyperref manual: "Make sure it comes last of your loaded
1990 // packages, to give it a fighting chance of not being over-written,
1991 // since its job is to redefine many LaTeX commands."
1992 // * Email from Heiko Oberdiek: "It is usually better to load babel
1993 // before hyperref. Then hyperref has a chance to detect babel.
1994 // * Has to be loaded before the "LyX specific LaTeX commands" to
1995 // avoid errors with algorithm floats.
1996 // use hyperref explicitly if it is required
1997 if (features.isRequired("hyperref")) {
1998 OutputParams tmp_params = features.runparams();
1999 pdfoptions().writeLaTeX(tmp_params, os,
2000 features.isProvided("hyperref"));
2001 // correctly break URLs with hyperref and dvi output
2002 if (features.runparams().flavor == OutputParams::LATEX
2003 && features.isAvailable("breakurl"))
2004 os << "\\usepackage{breakurl}\n";
2005 } else if (features.isRequired("nameref"))
2006 // hyperref loads this automatically
2007 os << "\\usepackage{nameref}\n";
2009 // bibtopic needs to be loaded after hyperref.
2010 // the dot provides the aux file naming which LyX can detect.
2011 if (features.mustProvide("bibtopic"))
2012 os << "\\usepackage[dot]{bibtopic}\n";
2014 // Will be surrounded by \makeatletter and \makeatother when not empty
2015 otexstringstream atlyxpreamble;
2017 // Some macros LyX will need
2019 TexString tmppreamble = features.getMacros();
2020 if (!tmppreamble.str.empty())
2021 atlyxpreamble << "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2022 "LyX specific LaTeX commands.\n"
2023 << move(tmppreamble)
2026 // the text class specific preamble
2028 docstring tmppreamble = features.getTClassPreamble();
2029 if (!tmppreamble.empty())
2030 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2031 "Textclass specific LaTeX commands.\n"
2035 // suppress date if selected
2036 // use \@ifundefined because we cannot be sure that every document class
2037 // has a \date command
2039 atlyxpreamble << "\\@ifundefined{date}{}{\\date{}}\n";
2041 /* the user-defined preamble */
2042 if (!containsOnly(preamble, " \n\t")) {
2044 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2045 "User specified LaTeX commands.\n";
2047 // Check if the user preamble contains uncodable glyphs
2048 odocstringstream user_preamble;
2049 docstring uncodable_glyphs;
2050 Encoding const * const enc = features.runparams().encoding;
2052 for (size_t n = 0; n < preamble.size(); ++n) {
2053 char_type c = preamble[n];
2054 if (!enc->encodable(c)) {
2055 docstring const glyph(1, c);
2056 LYXERR0("Uncodable character '"
2058 << "' in user preamble!");
2059 uncodable_glyphs += glyph;
2060 if (features.runparams().dryrun) {
2061 user_preamble << "<" << _("LyX Warning: ")
2062 << _("uncodable character") << " '";
2063 user_preamble.put(c);
2064 user_preamble << "'>";
2067 user_preamble.put(c);
2070 user_preamble << preamble;
2072 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2073 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2074 frontend::Alert::warning(
2075 _("Uncodable character in user preamble"),
2077 _("The user preamble of your document contains glyphs "
2078 "that are unknown in the current document encoding "
2079 "(namely %1$s).\nThese glyphs are omitted "
2080 " from the output, which may result in "
2081 "incomplete output."
2082 "\n\nPlease select an appropriate "
2083 "document encoding\n"
2084 "(such as utf8) or change the "
2085 "preamble code accordingly."),
2088 atlyxpreamble << user_preamble.str() << '\n';
2091 // footmisc must be loaded after setspace
2092 // Load it here to avoid clashes with footmisc loaded in the user
2093 // preamble. For that reason we also pass the options via
2094 // \PassOptionsToPackage in getPreamble() and not here.
2095 if (features.mustProvide("footmisc"))
2096 atlyxpreamble << "\\usepackage{footmisc}\n";
2098 // subfig loads internally the LaTeX package "caption". As
2099 // caption is a very popular package, users will load it in
2100 // the preamble. Therefore we must load subfig behind the
2101 // user-defined preamble and check if the caption package was
2102 // loaded or not. For the case that caption is loaded before
2103 // subfig, there is the subfig option "caption=false". This
2104 // option also works when a koma-script class is used and
2105 // koma's own caption commands are used instead of caption. We
2106 // use \PassOptionsToPackage here because the user could have
2107 // already loaded subfig in the preamble.
2108 if (features.mustProvide("subfig"))
2109 atlyxpreamble << "\\@ifundefined{showcaptionsetup}{}{%\n"
2110 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2111 "\\usepackage{subfig}\n";
2113 // Itemize bullet settings need to be last in case the user
2114 // defines their own bullets that use a package included
2115 // in the user-defined preamble -- ARRae
2116 // Actually it has to be done much later than that
2117 // since some packages like frenchb make modifications
2118 // at \begin{document} time -- JMarc
2119 docstring bullets_def;
2120 for (int i = 0; i < 4; ++i) {
2121 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2122 if (bullets_def.empty())
2123 bullets_def += "\\AtBeginDocument{\n";
2124 bullets_def += " \\def\\labelitemi";
2126 // `i' is one less than the item to modify
2133 bullets_def += "ii";
2139 bullets_def += '{' +
2140 user_defined_bullet(i).getText()
2145 if (!bullets_def.empty())
2146 atlyxpreamble << bullets_def << "}\n\n";
2148 if (!atlyxpreamble.empty())
2149 os << "\n\\makeatletter\n"
2150 << atlyxpreamble.release()
2151 << "\\makeatother\n\n";
2153 // We try to load babel late, in case it interferes with other packages.
2154 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2155 // called after babel, though.
2156 if (use_babel && !features.isRequired("jurabib")
2157 && !features.isRequired("hyperref")
2158 && !features.isRequired("varioref")
2159 && !features.isRequired("vietnamese")
2160 && !features.isRequired("japanese")) {
2161 os << features.getBabelPresettings();
2163 os << from_utf8(babelCall(language_options.str(),
2164 features.needBabelLangOptions())) + '\n';
2165 os << features.getBabelPostsettings();
2167 if (features.isRequired("bicaption"))
2168 os << "\\usepackage{bicaption}\n";
2169 if (!listings_params.empty() || features.mustProvide("listings"))
2170 os << "\\usepackage{listings}\n";
2171 if (!listings_params.empty()) {
2173 // do not test validity because listings_params is
2174 // supposed to be valid
2176 InsetListingsParams(listings_params).separatedParams(true);
2177 os << from_utf8(par);
2181 // xunicode needs to be loaded at least after amsmath, amssymb,
2182 // esint and the other packages that provide special glyphs
2183 // The package only supports XeTeX currently.
2184 if (features.runparams().flavor == OutputParams::XETEX
2186 os << "\\usepackage{xunicode}\n";
2188 // Polyglossia must be loaded last
2189 if (use_polyglossia) {
2191 os << "\\usepackage{polyglossia}\n";
2192 // set the main language
2193 os << "\\setdefaultlanguage";
2194 if (!language->polyglossiaOpts().empty())
2195 os << "[" << from_ascii(language->polyglossiaOpts()) << "]";
2196 os << "{" << from_ascii(language->polyglossia()) << "}\n";
2197 // now setup the other languages
2198 set<string> const polylangs =
2199 features.getPolyglossiaLanguages();
2200 for (set<string>::const_iterator mit = polylangs.begin();
2201 mit != polylangs.end() ; ++mit) {
2202 // We do not output the options here; they are output in
2203 // the language switch commands. This is safer if multiple
2204 // varieties are used.
2205 if (*mit == language->polyglossia())
2207 os << "\\setotherlanguage";
2208 os << "{" << from_ascii(*mit) << "}\n";
2212 // Load custom language package here
2213 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2214 if (lang_package == "default")
2215 os << from_utf8(lyxrc.language_custom_package);
2217 os << from_utf8(lang_package);
2221 docstring const i18npreamble =
2222 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2223 if (!i18npreamble.empty())
2224 os << i18npreamble + '\n';
2230 void BufferParams::useClassDefaults()
2232 DocumentClass const & tclass = documentClass();
2234 sides = tclass.sides();
2235 columns = tclass.columns();
2236 pagestyle = tclass.pagestyle();
2237 use_default_options = true;
2238 // Only if class has a ToC hierarchy
2239 if (tclass.hasTocLevels()) {
2240 secnumdepth = tclass.secnumdepth();
2241 tocdepth = tclass.tocdepth();
2246 bool BufferParams::hasClassDefaults() const
2248 DocumentClass const & tclass = documentClass();
2250 return sides == tclass.sides()
2251 && columns == tclass.columns()
2252 && pagestyle == tclass.pagestyle()
2253 && use_default_options
2254 && secnumdepth == tclass.secnumdepth()
2255 && tocdepth == tclass.tocdepth();
2259 DocumentClass const & BufferParams::documentClass() const
2265 DocumentClassConstPtr BufferParams::documentClassPtr() const
2271 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2273 // evil, but this function is evil
2274 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2275 invalidateConverterCache();
2279 bool BufferParams::setBaseClass(string const & classname)
2281 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2282 LayoutFileList & bcl = LayoutFileList::get();
2283 if (!bcl.haveClass(classname)) {
2285 bformat(_("The layout file:\n"
2287 "could not be found. A default textclass with default\n"
2288 "layouts will be used. LyX will not be able to produce\n"
2290 from_utf8(classname));
2291 frontend::Alert::error(_("Document class not found"), s);
2292 bcl.addEmptyClass(classname);
2295 bool const success = bcl[classname].load();
2298 bformat(_("Due to some error in it, the layout file:\n"
2300 "could not be loaded. A default textclass with default\n"
2301 "layouts will be used. LyX will not be able to produce\n"
2303 from_utf8(classname));
2304 frontend::Alert::error(_("Could not load class"), s);
2305 bcl.addEmptyClass(classname);
2308 pimpl_->baseClass_ = classname;
2309 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2314 LayoutFile const * BufferParams::baseClass() const
2316 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2317 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2323 LayoutFileIndex const & BufferParams::baseClassID() const
2325 return pimpl_->baseClass_;
2329 void BufferParams::makeDocumentClass(bool const clone)
2334 invalidateConverterCache();
2335 LayoutModuleList mods;
2336 LayoutModuleList ces;
2337 LayoutModuleList::iterator it = layout_modules_.begin();
2338 LayoutModuleList::iterator en = layout_modules_.end();
2339 for (; it != en; ++it)
2340 mods.push_back(*it);
2342 it = cite_engine_.begin();
2343 en = cite_engine_.end();
2344 for (; it != en; ++it)
2347 doc_class_ = getDocumentClass(*baseClass(), mods, ces, clone);
2349 TextClass::ReturnValues success = TextClass::OK;
2350 if (!forced_local_layout_.empty())
2351 success = doc_class_->read(to_utf8(forced_local_layout_),
2353 if (!local_layout_.empty() &&
2354 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2355 success = doc_class_->read(to_utf8(local_layout_), TextClass::MODULE);
2356 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2357 docstring const msg = _("Error reading internal layout information");
2358 frontend::Alert::warning(_("Read Error"), msg);
2363 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2365 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2369 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2371 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2375 docstring BufferParams::getLocalLayout(bool forced) const
2378 return from_utf8(doc_class_->forcedLayouts());
2380 return local_layout_;
2384 void BufferParams::setLocalLayout(docstring const & layout, bool forced)
2387 forced_local_layout_ = layout;
2389 local_layout_ = layout;
2393 bool BufferParams::addLayoutModule(string const & modName)
2395 LayoutModuleList::const_iterator it = layout_modules_.begin();
2396 LayoutModuleList::const_iterator end = layout_modules_.end();
2397 for (; it != end; ++it)
2400 layout_modules_.push_back(modName);
2405 string BufferParams::bufferFormat() const
2407 return documentClass().outputFormat();
2411 bool BufferParams::isExportable(string const & format, bool need_viewable) const
2413 FormatList const & formats = exportableFormats(need_viewable);
2414 FormatList::const_iterator fit = formats.begin();
2415 FormatList::const_iterator end = formats.end();
2416 for (; fit != end ; ++fit) {
2417 if ((*fit)->name() == format)
2424 FormatList const & BufferParams::exportableFormats(bool only_viewable) const
2426 FormatList & cached = only_viewable ?
2427 pimpl_->viewableFormatList : pimpl_->exportableFormatList;
2428 bool & valid = only_viewable ?
2429 pimpl_->isViewCacheValid : pimpl_->isExportCacheValid;
2433 vector<string> const backs = backends();
2434 set<string> excludes;
2435 if (useNonTeXFonts) {
2436 excludes.insert("latex");
2437 excludes.insert("pdflatex");
2440 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2441 for (vector<string>::const_iterator it = backs.begin() + 1;
2442 it != backs.end(); ++it) {
2443 FormatList r = theConverters().getReachable(*it, only_viewable,
2445 result.insert(result.end(), r.begin(), r.end());
2447 sort(result.begin(), result.end(), Format::formatSorter);
2454 vector<string> BufferParams::backends() const
2457 string const buffmt = bufferFormat();
2459 // FIXME: Don't hardcode format names here, but use a flag
2460 if (buffmt == "latex") {
2461 if (encoding().package() == Encoding::japanese)
2462 v.push_back("platex");
2464 if (!useNonTeXFonts) {
2465 v.push_back("pdflatex");
2466 v.push_back("latex");
2468 v.push_back("xetex");
2469 v.push_back("luatex");
2470 v.push_back("dviluatex");
2473 v.push_back(buffmt);
2475 v.push_back("xhtml");
2476 v.push_back("text");
2482 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2484 string const dformat = (format.empty() || format == "default") ?
2485 getDefaultOutputFormat() : format;
2486 DefaultFlavorCache::const_iterator it =
2487 default_flavors_.find(dformat);
2489 if (it != default_flavors_.end())
2492 OutputParams::FLAVOR result = OutputParams::LATEX;
2494 // FIXME It'd be better not to hardcode this, but to do
2495 // something with formats.
2496 if (dformat == "xhtml")
2497 result = OutputParams::HTML;
2498 else if (dformat == "text")
2499 result = OutputParams::TEXT;
2500 else if (dformat == "lyx")
2501 result = OutputParams::LYX;
2502 else if (dformat == "pdflatex")
2503 result = OutputParams::PDFLATEX;
2504 else if (dformat == "xetex")
2505 result = OutputParams::XETEX;
2506 else if (dformat == "luatex")
2507 result = OutputParams::LUATEX;
2508 else if (dformat == "dviluatex")
2509 result = OutputParams::DVILUATEX;
2511 // Try to determine flavor of default output format
2512 vector<string> backs = backends();
2513 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2514 // Get shortest path to format
2515 Graph::EdgePath path;
2516 for (vector<string>::const_iterator it = backs.begin();
2517 it != backs.end(); ++it) {
2518 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2519 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2524 result = theConverters().getFlavor(path);
2527 // cache this flavor
2528 default_flavors_[dformat] = result;
2533 string BufferParams::getDefaultOutputFormat() const
2535 if (!default_output_format.empty()
2536 && default_output_format != "default")
2537 return default_output_format;
2539 || encoding().package() == Encoding::japanese) {
2540 FormatList const & formats = exportableFormats(true);
2541 if (formats.empty())
2543 // return the first we find
2544 return formats.front()->name();
2547 return lyxrc.default_otf_view_format;
2548 return lyxrc.default_view_format;
2551 Font const BufferParams::getFont() const
2553 FontInfo f = documentClass().defaultfont();
2554 if (fonts_default_family == "rmdefault")
2555 f.setFamily(ROMAN_FAMILY);
2556 else if (fonts_default_family == "sfdefault")
2557 f.setFamily(SANS_FAMILY);
2558 else if (fonts_default_family == "ttdefault")
2559 f.setFamily(TYPEWRITER_FAMILY);
2560 return Font(f, language);
2564 InsetQuotesParams::QuoteStyle BufferParams::getQuoteStyle(string const & qs) const
2566 return quotesstyletranslator().find(qs);
2570 bool BufferParams::isLatex() const
2572 return documentClass().outputType() == LATEX;
2576 bool BufferParams::isLiterate() const
2578 return documentClass().outputType() == LITERATE;
2582 bool BufferParams::isDocBook() const
2584 return documentClass().outputType() == DOCBOOK;
2588 void BufferParams::readPreamble(Lexer & lex)
2590 if (lex.getString() != "\\begin_preamble")
2591 lyxerr << "Error (BufferParams::readPreamble):"
2592 "consistency check failed." << endl;
2594 preamble = lex.getLongString(from_ascii("\\end_preamble"));
2598 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2600 string const expected = forced ? "\\begin_forced_local_layout" :
2601 "\\begin_local_layout";
2602 if (lex.getString() != expected)
2603 lyxerr << "Error (BufferParams::readLocalLayout):"
2604 "consistency check failed." << endl;
2607 forced_local_layout_ =
2608 lex.getLongString(from_ascii("\\end_forced_local_layout"));
2610 local_layout_ = lex.getLongString(from_ascii("\\end_local_layout"));
2614 bool BufferParams::setLanguage(string const & lang)
2616 Language const *new_language = languages.getLanguage(lang);
2617 if (!new_language) {
2618 // Language lang was not found
2621 language = new_language;
2626 void BufferParams::readLanguage(Lexer & lex)
2628 if (!lex.next()) return;
2630 string const tmptok = lex.getString();
2632 // check if tmptok is part of tex_babel in tex-defs.h
2633 if (!setLanguage(tmptok)) {
2634 // Language tmptok was not found
2635 language = default_language;
2636 lyxerr << "Warning: Setting language `"
2637 << tmptok << "' to `" << language->lang()
2643 void BufferParams::readGraphicsDriver(Lexer & lex)
2648 string const tmptok = lex.getString();
2649 // check if tmptok is part of tex_graphics in tex_defs.h
2652 string const test = tex_graphics[n++];
2654 if (test == tmptok) {
2655 graphics_driver = tmptok;
2660 "Warning: graphics driver `$$Token' not recognized!\n"
2661 " Setting graphics driver to `default'.\n");
2662 graphics_driver = "default";
2669 void BufferParams::readBullets(Lexer & lex)
2674 int const index = lex.getInteger();
2676 int temp_int = lex.getInteger();
2677 user_defined_bullet(index).setFont(temp_int);
2678 temp_bullet(index).setFont(temp_int);
2680 user_defined_bullet(index).setCharacter(temp_int);
2681 temp_bullet(index).setCharacter(temp_int);
2683 user_defined_bullet(index).setSize(temp_int);
2684 temp_bullet(index).setSize(temp_int);
2688 void BufferParams::readBulletsLaTeX(Lexer & lex)
2690 // The bullet class should be able to read this.
2693 int const index = lex.getInteger();
2695 docstring const temp_str = lex.getDocString();
2697 user_defined_bullet(index).setText(temp_str);
2698 temp_bullet(index).setText(temp_str);
2702 void BufferParams::readModules(Lexer & lex)
2704 if (!lex.eatLine()) {
2705 lyxerr << "Error (BufferParams::readModules):"
2706 "Unexpected end of input." << endl;
2710 string mod = lex.getString();
2711 if (mod == "\\end_modules")
2713 addLayoutModule(mod);
2719 void BufferParams::readRemovedModules(Lexer & lex)
2721 if (!lex.eatLine()) {
2722 lyxerr << "Error (BufferParams::readRemovedModules):"
2723 "Unexpected end of input." << endl;
2727 string mod = lex.getString();
2728 if (mod == "\\end_removed_modules")
2730 removed_modules_.push_back(mod);
2733 // now we want to remove any removed modules that were previously
2734 // added. normally, that will be because default modules were added in
2735 // setBaseClass(), which gets called when \textclass is read at the
2736 // start of the read.
2737 list<string>::const_iterator rit = removed_modules_.begin();
2738 list<string>::const_iterator const ren = removed_modules_.end();
2739 for (; rit != ren; ++rit) {
2740 LayoutModuleList::iterator const mit = layout_modules_.begin();
2741 LayoutModuleList::iterator const men = layout_modules_.end();
2742 LayoutModuleList::iterator found = find(mit, men, *rit);
2745 layout_modules_.erase(found);
2750 void BufferParams::readIncludeonly(Lexer & lex)
2752 if (!lex.eatLine()) {
2753 lyxerr << "Error (BufferParams::readIncludeonly):"
2754 "Unexpected end of input." << endl;
2758 string child = lex.getString();
2759 if (child == "\\end_includeonly")
2761 included_children_.push_back(child);
2767 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2769 switch (papersize) {
2771 // could be anything, so don't guess
2773 case PAPER_CUSTOM: {
2774 if (purpose == XDVI && !paperwidth.empty() &&
2775 !paperheight.empty()) {
2776 // heightxwidth<unit>
2777 string first = paperwidth;
2778 string second = paperheight;
2779 if (orientation == ORIENTATION_LANDSCAPE)
2782 return first.erase(first.length() - 2)
2788 // dvips and dvipdfm do not know this
2789 if (purpose == DVIPS || purpose == DVIPDFM)
2793 if (purpose == DVIPS || purpose == DVIPDFM)
2797 if (purpose == DVIPS || purpose == DVIPDFM)
2807 if (purpose == DVIPS || purpose == DVIPDFM)
2811 if (purpose == DVIPS || purpose == DVIPDFM)
2815 if (purpose == DVIPS || purpose == DVIPDFM)
2819 if (purpose == DVIPS || purpose == DVIPDFM)
2823 if (purpose == DVIPS || purpose == DVIPDFM)
2827 // dvipdfm does not know this
2828 if (purpose == DVIPDFM)
2832 if (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)
2876 if (purpose == DVIPS || purpose == DVIPDFM)
2880 if (purpose == DVIPS || purpose == DVIPDFM)
2884 if (purpose == DVIPS || purpose == DVIPDFM)
2888 if (purpose == DVIPS || purpose == DVIPDFM)
2892 if (purpose == DVIPS || purpose == DVIPDFM)
2895 case PAPER_USEXECUTIVE:
2896 // dvipdfm does not know this
2897 if (purpose == DVIPDFM)
2902 case PAPER_USLETTER:
2904 if (purpose == XDVI)
2911 string const BufferParams::dvips_options() const
2915 // If the class loads the geometry package, we do not know which
2916 // paper size is used, since we do not set it (bug 7013).
2917 // Therefore we must not specify any argument here.
2918 // dvips gets the correct paper size via DVI specials in this case
2919 // (if the class uses the geometry package correctly).
2920 if (documentClass().provides("geometry"))
2924 && papersize == PAPER_CUSTOM
2925 && !lyxrc.print_paper_dimension_flag.empty()
2926 && !paperwidth.empty()
2927 && !paperheight.empty()) {
2928 // using a custom papersize
2929 result = lyxrc.print_paper_dimension_flag;
2930 result += ' ' + paperwidth;
2931 result += ',' + paperheight;
2933 string const paper_option = paperSizeName(DVIPS);
2934 if (!paper_option.empty() && (paper_option != "letter" ||
2935 orientation != ORIENTATION_LANDSCAPE)) {
2936 // dvips won't accept -t letter -t landscape.
2937 // In all other cases, include the paper size
2939 result = lyxrc.print_paper_flag;
2940 result += ' ' + paper_option;
2943 if (orientation == ORIENTATION_LANDSCAPE &&
2944 papersize != PAPER_CUSTOM)
2945 result += ' ' + lyxrc.print_landscape_flag;
2950 string const BufferParams::font_encoding() const
2952 return font_encodings().empty() ? "default" : font_encodings().back();
2956 vector<string> const BufferParams::font_encodings() const
2958 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2960 vector<string> fontencs;
2962 // "default" means "no explicit font encoding"
2963 if (doc_fontenc != "default") {
2964 fontencs = getVectorFromString(doc_fontenc);
2965 if (!language->fontenc().empty()
2966 && ascii_lowercase(language->fontenc()) != "none") {
2967 vector<string> fencs = getVectorFromString(language->fontenc());
2968 vector<string>::const_iterator fit = fencs.begin();
2969 for (; fit != fencs.end(); ++fit) {
2970 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2971 fontencs.push_back(*fit);
2980 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2982 // suppress the babel call if there is no BabelName defined
2983 // for the document language in the lib/languages file and if no
2984 // other languages are used (lang_opts is then empty)
2985 if (lang_opts.empty())
2987 // either a specific language (AsBabelOptions setting in
2988 // lib/languages) or the prefs require the languages to
2989 // be submitted to babel itself (not the class).
2991 return "\\usepackage[" + lang_opts + "]{babel}";
2992 return "\\usepackage{babel}";
2996 docstring BufferParams::getGraphicsDriver(string const & package) const
3000 if (package == "geometry") {
3001 if (graphics_driver == "dvips"
3002 || graphics_driver == "dvipdfm"
3003 || graphics_driver == "pdftex"
3004 || graphics_driver == "vtex")
3005 result = from_ascii(graphics_driver);
3006 else if (graphics_driver == "dvipdfmx")
3007 result = from_ascii("dvipdfm");
3014 void BufferParams::writeEncodingPreamble(otexstream & os,
3015 LaTeXFeatures & features) const
3017 // XeTeX/LuaTeX: (see also #9740)
3018 // With Unicode fonts we use utf8-plain without encoding package.
3019 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
3020 // XeTeX must use ASCII encoding (see Buffer.cpp),
3021 // for LuaTeX, we load "luainputenc" (see below).
3022 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
3025 if (inputenc == "auto") {
3026 string const doc_encoding =
3027 language->encoding()->latexName();
3028 Encoding::Package const package =
3029 language->encoding()->package();
3031 // Create list of inputenc options:
3032 set<string> encodings;
3033 // luainputenc fails with more than one encoding
3034 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
3035 // list all input encodings used in the document
3036 encodings = features.getEncodingSet(doc_encoding);
3038 // If the "japanese" package (i.e. pLaTeX) is used,
3039 // inputenc must be omitted.
3040 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
3041 if ((!encodings.empty() || package == Encoding::inputenc)
3042 && !features.isRequired("japanese")
3043 && !features.isProvided("inputenc")) {
3044 os << "\\usepackage[";
3045 set<string>::const_iterator it = encodings.begin();
3046 set<string>::const_iterator const end = encodings.end();
3048 os << from_ascii(*it);
3051 for (; it != end; ++it)
3052 os << ',' << from_ascii(*it);
3053 if (package == Encoding::inputenc) {
3054 if (!encodings.empty())
3056 os << from_ascii(doc_encoding);
3058 if (features.runparams().flavor == OutputParams::LUATEX
3059 || features.runparams().flavor == OutputParams::DVILUATEX)
3060 os << "]{luainputenc}\n";
3062 os << "]{inputenc}\n";
3064 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3065 if (language->encoding()->name() == "utf8-cjk"
3066 && LaTeXFeatures::isAvailable("CJKutf8"))
3067 os << "\\usepackage{CJKutf8}\n";
3069 os << "\\usepackage{CJK}\n";
3071 } else if (inputenc != "default") {
3072 switch (encoding().package()) {
3073 case Encoding::none:
3074 case Encoding::japanese:
3076 case Encoding::inputenc:
3077 // do not load inputenc if japanese is used
3078 // or if the class provides inputenc
3079 if (features.isRequired("japanese")
3080 || features.isProvided("inputenc"))
3082 os << "\\usepackage[" << from_ascii(encoding().latexName());
3083 if (features.runparams().flavor == OutputParams::LUATEX
3084 || features.runparams().flavor == OutputParams::DVILUATEX)
3085 os << "]{luainputenc}\n";
3087 os << "]{inputenc}\n";
3090 if (encoding().name() == "utf8-cjk"
3091 && LaTeXFeatures::isAvailable("CJKutf8"))
3092 os << "\\usepackage{CJKutf8}\n";
3094 os << "\\usepackage{CJK}\n";
3097 // Load the CJK package if needed by a secondary language.
3098 // If the main encoding is some variant of UTF8, use CJKutf8.
3099 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3100 if (encoding().iconvName() == "UTF-8"
3101 && LaTeXFeatures::isAvailable("CJKutf8"))
3102 os << "\\usepackage{CJKutf8}\n";
3104 os << "\\usepackage{CJK}\n";
3110 string const BufferParams::parseFontName(string const & name) const
3112 string mangled = name;
3113 size_t const idx = mangled.find('[');
3114 if (idx == string::npos || idx == 0)
3117 return mangled.substr(0, idx - 1);
3121 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3123 if (fontsRoman() == "default" && fontsSans() == "default"
3124 && fontsTypewriter() == "default"
3125 && (fontsMath() == "default" || fontsMath() == "auto"))
3131 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3132 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3133 * Mapping=tex-text option assures TeX ligatures (such as "--")
3134 * are resolved. Note that tt does not use these ligatures.
3136 * -- add more GUI options?
3137 * -- add more fonts (fonts for other scripts)
3138 * -- if there's a way to find out if a font really supports
3139 * OldStyle, enable/disable the widget accordingly.
3141 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3142 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3143 // However, until v.2 (2010/07/11) fontspec only knew
3144 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3145 // was introduced for both XeTeX and LuaTeX (LuaTeX
3146 // didn't understand "Mapping=tex-text", while XeTeX
3147 // understood both. With most recent versions, both
3148 // variants are understood by both engines. However,
3149 // we want to provide support for at least TeXLive 2009
3150 // (for XeTeX; LuaTeX is only supported as of v.2)
3151 string const texmapping =
3152 (features.runparams().flavor == OutputParams::XETEX) ?
3153 "Mapping=tex-text" : "Ligatures=TeX";
3154 if (fontsRoman() != "default") {
3155 os << "\\setmainfont[" << texmapping;
3156 if (fonts_old_figures)
3157 os << ",Numbers=OldStyle";
3158 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3160 if (fontsSans() != "default") {
3161 string const sans = parseFontName(fontsSans());
3162 if (fontsSansScale() != 100)
3163 os << "\\setsansfont[Scale="
3164 << float(fontsSansScale()) / 100
3165 << "," << texmapping << "]{"
3168 os << "\\setsansfont[" << texmapping << "]{"
3171 if (fontsTypewriter() != "default") {
3172 string const mono = parseFontName(fontsTypewriter());
3173 if (fontsTypewriterScale() != 100)
3174 os << "\\setmonofont[Scale="
3175 << float(fontsTypewriterScale()) / 100
3179 os << "\\setmonofont{"
3186 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3187 bool const dryrun = features.runparams().dryrun;
3188 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3189 bool const nomath = (fontsMath() == "default");
3192 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3193 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3197 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3198 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3199 nomath, fontsSansScale());
3201 // MONOSPACED/TYPEWRITER
3202 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3203 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3204 nomath, fontsTypewriterScale());
3207 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3208 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3215 Encoding const & BufferParams::encoding() const
3217 // Main encoding for LaTeX output.
3219 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3220 // As the "flavor" is only known once export started, this
3221 // cannot be handled here. Instead, runparams.encoding is set
3222 // to ASCII in Buffer::makeLaTeXFile (for export)
3223 // and Buffer::writeLaTeXSource (for preview).
3225 return *(encodings.fromLyXName("utf8-plain"));
3226 if (inputenc == "auto" || inputenc == "default")
3227 return *language->encoding();
3228 Encoding const * const enc = encodings.fromLyXName(inputenc);
3231 LYXERR0("Unknown inputenc value `" << inputenc
3232 << "'. Using `auto' instead.");
3233 return *language->encoding();
3237 bool BufferParams::addCiteEngine(string const & engine)
3239 LayoutModuleList::const_iterator it = cite_engine_.begin();
3240 LayoutModuleList::const_iterator en = cite_engine_.end();
3241 for (; it != en; ++it)
3244 cite_engine_.push_back(engine);
3249 bool BufferParams::addCiteEngine(vector<string> const & engine)
3251 vector<string>::const_iterator it = engine.begin();
3252 vector<string>::const_iterator en = engine.end();
3254 for (; it != en; ++it)
3255 if (!addCiteEngine(*it))
3261 string const & BufferParams::defaultBiblioStyle() const
3263 return documentClass().defaultBiblioStyle();
3267 bool const & BufferParams::fullAuthorList() const
3269 return documentClass().fullAuthorList();
3273 void BufferParams::setCiteEngine(string const & engine)
3276 addCiteEngine(engine);
3280 void BufferParams::setCiteEngine(vector<string> const & engine)
3283 addCiteEngine(engine);
3287 vector<string> BufferParams::citeCommands() const
3289 static CitationStyle const default_style;
3290 vector<string> commands =
3291 documentClass().citeCommands(citeEngineType());
3292 if (commands.empty())
3293 commands.push_back(default_style.cmd);
3298 vector<CitationStyle> BufferParams::citeStyles() const
3300 static CitationStyle const default_style;
3301 vector<CitationStyle> styles =
3302 documentClass().citeStyles(citeEngineType());
3304 styles.push_back(default_style);
3308 void BufferParams::invalidateConverterCache() const
3310 pimpl_->isExportCacheValid = false;
3311 pimpl_->isViewCacheValid = false;