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::iterator it = layout_modules_.begin();
2337 LayoutModuleList::iterator en = layout_modules_.end();
2338 for (; it != en; ++it)
2339 mods.push_back(*it);
2341 it = cite_engine_.begin();
2342 en = cite_engine_.end();
2343 for (; it != en; ++it)
2344 mods.push_back(*it);
2346 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2348 TextClass::ReturnValues success = TextClass::OK;
2349 if (!forced_local_layout_.empty())
2350 success = doc_class_->read(to_utf8(forced_local_layout_),
2352 if (!local_layout_.empty() &&
2353 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2354 success = doc_class_->read(to_utf8(local_layout_), TextClass::MODULE);
2355 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2356 docstring const msg = _("Error reading internal layout information");
2357 frontend::Alert::warning(_("Read Error"), msg);
2362 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2364 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2368 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2370 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2374 docstring BufferParams::getLocalLayout(bool forced) const
2377 return from_utf8(doc_class_->forcedLayouts());
2379 return local_layout_;
2383 void BufferParams::setLocalLayout(docstring const & layout, bool forced)
2386 forced_local_layout_ = layout;
2388 local_layout_ = layout;
2392 bool BufferParams::addLayoutModule(string const & modName)
2394 LayoutModuleList::const_iterator it = layout_modules_.begin();
2395 LayoutModuleList::const_iterator end = layout_modules_.end();
2396 for (; it != end; ++it)
2399 layout_modules_.push_back(modName);
2404 string BufferParams::bufferFormat() const
2406 return documentClass().outputFormat();
2410 bool BufferParams::isExportable(string const & format, bool need_viewable) const
2412 FormatList const & formats = exportableFormats(need_viewable);
2413 FormatList::const_iterator fit = formats.begin();
2414 FormatList::const_iterator end = formats.end();
2415 for (; fit != end ; ++fit) {
2416 if ((*fit)->name() == format)
2423 FormatList const & BufferParams::exportableFormats(bool only_viewable) const
2425 FormatList & cached = only_viewable ?
2426 pimpl_->viewableFormatList : pimpl_->exportableFormatList;
2427 bool & valid = only_viewable ?
2428 pimpl_->isViewCacheValid : pimpl_->isExportCacheValid;
2432 vector<string> const backs = backends();
2433 set<string> excludes;
2434 if (useNonTeXFonts) {
2435 excludes.insert("latex");
2436 excludes.insert("pdflatex");
2439 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2440 for (vector<string>::const_iterator it = backs.begin() + 1;
2441 it != backs.end(); ++it) {
2442 FormatList r = theConverters().getReachable(*it, only_viewable,
2444 result.insert(result.end(), r.begin(), r.end());
2446 sort(result.begin(), result.end(), Format::formatSorter);
2453 vector<string> BufferParams::backends() const
2456 string const buffmt = bufferFormat();
2458 // FIXME: Don't hardcode format names here, but use a flag
2459 if (buffmt == "latex") {
2460 if (encoding().package() == Encoding::japanese)
2461 v.push_back("platex");
2463 if (!useNonTeXFonts) {
2464 v.push_back("pdflatex");
2465 v.push_back("latex");
2467 v.push_back("xetex");
2468 v.push_back("luatex");
2469 v.push_back("dviluatex");
2472 v.push_back(buffmt);
2474 v.push_back("xhtml");
2475 v.push_back("text");
2481 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2483 string const dformat = (format.empty() || format == "default") ?
2484 getDefaultOutputFormat() : format;
2485 DefaultFlavorCache::const_iterator it =
2486 default_flavors_.find(dformat);
2488 if (it != default_flavors_.end())
2491 OutputParams::FLAVOR result = OutputParams::LATEX;
2493 // FIXME It'd be better not to hardcode this, but to do
2494 // something with formats.
2495 if (dformat == "xhtml")
2496 result = OutputParams::HTML;
2497 else if (dformat == "text")
2498 result = OutputParams::TEXT;
2499 else if (dformat == "lyx")
2500 result = OutputParams::LYX;
2501 else if (dformat == "pdflatex")
2502 result = OutputParams::PDFLATEX;
2503 else if (dformat == "xetex")
2504 result = OutputParams::XETEX;
2505 else if (dformat == "luatex")
2506 result = OutputParams::LUATEX;
2507 else if (dformat == "dviluatex")
2508 result = OutputParams::DVILUATEX;
2510 // Try to determine flavor of default output format
2511 vector<string> backs = backends();
2512 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2513 // Get shortest path to format
2514 Graph::EdgePath path;
2515 for (vector<string>::const_iterator it = backs.begin();
2516 it != backs.end(); ++it) {
2517 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2518 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2523 result = theConverters().getFlavor(path);
2526 // cache this flavor
2527 default_flavors_[dformat] = result;
2532 string BufferParams::getDefaultOutputFormat() const
2534 if (!default_output_format.empty()
2535 && default_output_format != "default")
2536 return default_output_format;
2538 || encoding().package() == Encoding::japanese) {
2539 FormatList const & formats = exportableFormats(true);
2540 if (formats.empty())
2542 // return the first we find
2543 return formats.front()->name();
2546 return lyxrc.default_otf_view_format;
2547 return lyxrc.default_view_format;
2550 Font const BufferParams::getFont() const
2552 FontInfo f = documentClass().defaultfont();
2553 if (fonts_default_family == "rmdefault")
2554 f.setFamily(ROMAN_FAMILY);
2555 else if (fonts_default_family == "sfdefault")
2556 f.setFamily(SANS_FAMILY);
2557 else if (fonts_default_family == "ttdefault")
2558 f.setFamily(TYPEWRITER_FAMILY);
2559 return Font(f, language);
2563 InsetQuotesParams::QuoteStyle BufferParams::getQuoteStyle(string const & qs) const
2565 return quotesstyletranslator().find(qs);
2569 bool BufferParams::isLatex() const
2571 return documentClass().outputType() == LATEX;
2575 bool BufferParams::isLiterate() const
2577 return documentClass().outputType() == LITERATE;
2581 bool BufferParams::isDocBook() const
2583 return documentClass().outputType() == DOCBOOK;
2587 void BufferParams::readPreamble(Lexer & lex)
2589 if (lex.getString() != "\\begin_preamble")
2590 lyxerr << "Error (BufferParams::readPreamble):"
2591 "consistency check failed." << endl;
2593 preamble = lex.getLongString(from_ascii("\\end_preamble"));
2597 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2599 string const expected = forced ? "\\begin_forced_local_layout" :
2600 "\\begin_local_layout";
2601 if (lex.getString() != expected)
2602 lyxerr << "Error (BufferParams::readLocalLayout):"
2603 "consistency check failed." << endl;
2606 forced_local_layout_ =
2607 lex.getLongString(from_ascii("\\end_forced_local_layout"));
2609 local_layout_ = lex.getLongString(from_ascii("\\end_local_layout"));
2613 bool BufferParams::setLanguage(string const & lang)
2615 Language const *new_language = languages.getLanguage(lang);
2616 if (!new_language) {
2617 // Language lang was not found
2620 language = new_language;
2625 void BufferParams::readLanguage(Lexer & lex)
2627 if (!lex.next()) return;
2629 string const tmptok = lex.getString();
2631 // check if tmptok is part of tex_babel in tex-defs.h
2632 if (!setLanguage(tmptok)) {
2633 // Language tmptok was not found
2634 language = default_language;
2635 lyxerr << "Warning: Setting language `"
2636 << tmptok << "' to `" << language->lang()
2642 void BufferParams::readGraphicsDriver(Lexer & lex)
2647 string const tmptok = lex.getString();
2648 // check if tmptok is part of tex_graphics in tex_defs.h
2651 string const test = tex_graphics[n++];
2653 if (test == tmptok) {
2654 graphics_driver = tmptok;
2659 "Warning: graphics driver `$$Token' not recognized!\n"
2660 " Setting graphics driver to `default'.\n");
2661 graphics_driver = "default";
2668 void BufferParams::readBullets(Lexer & lex)
2673 int const index = lex.getInteger();
2675 int temp_int = lex.getInteger();
2676 user_defined_bullet(index).setFont(temp_int);
2677 temp_bullet(index).setFont(temp_int);
2679 user_defined_bullet(index).setCharacter(temp_int);
2680 temp_bullet(index).setCharacter(temp_int);
2682 user_defined_bullet(index).setSize(temp_int);
2683 temp_bullet(index).setSize(temp_int);
2687 void BufferParams::readBulletsLaTeX(Lexer & lex)
2689 // The bullet class should be able to read this.
2692 int const index = lex.getInteger();
2694 docstring const temp_str = lex.getDocString();
2696 user_defined_bullet(index).setText(temp_str);
2697 temp_bullet(index).setText(temp_str);
2701 void BufferParams::readModules(Lexer & lex)
2703 if (!lex.eatLine()) {
2704 lyxerr << "Error (BufferParams::readModules):"
2705 "Unexpected end of input." << endl;
2709 string mod = lex.getString();
2710 if (mod == "\\end_modules")
2712 addLayoutModule(mod);
2718 void BufferParams::readRemovedModules(Lexer & lex)
2720 if (!lex.eatLine()) {
2721 lyxerr << "Error (BufferParams::readRemovedModules):"
2722 "Unexpected end of input." << endl;
2726 string mod = lex.getString();
2727 if (mod == "\\end_removed_modules")
2729 removed_modules_.push_back(mod);
2732 // now we want to remove any removed modules that were previously
2733 // added. normally, that will be because default modules were added in
2734 // setBaseClass(), which gets called when \textclass is read at the
2735 // start of the read.
2736 list<string>::const_iterator rit = removed_modules_.begin();
2737 list<string>::const_iterator const ren = removed_modules_.end();
2738 for (; rit != ren; ++rit) {
2739 LayoutModuleList::iterator const mit = layout_modules_.begin();
2740 LayoutModuleList::iterator const men = layout_modules_.end();
2741 LayoutModuleList::iterator found = find(mit, men, *rit);
2744 layout_modules_.erase(found);
2749 void BufferParams::readIncludeonly(Lexer & lex)
2751 if (!lex.eatLine()) {
2752 lyxerr << "Error (BufferParams::readIncludeonly):"
2753 "Unexpected end of input." << endl;
2757 string child = lex.getString();
2758 if (child == "\\end_includeonly")
2760 included_children_.push_back(child);
2766 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2768 switch (papersize) {
2770 // could be anything, so don't guess
2772 case PAPER_CUSTOM: {
2773 if (purpose == XDVI && !paperwidth.empty() &&
2774 !paperheight.empty()) {
2775 // heightxwidth<unit>
2776 string first = paperwidth;
2777 string second = paperheight;
2778 if (orientation == ORIENTATION_LANDSCAPE)
2781 return first.erase(first.length() - 2)
2787 // dvips and dvipdfm do not know this
2788 if (purpose == DVIPS || purpose == DVIPDFM)
2792 if (purpose == DVIPS || purpose == DVIPDFM)
2796 if (purpose == DVIPS || purpose == DVIPDFM)
2806 if (purpose == DVIPS || purpose == DVIPDFM)
2810 if (purpose == DVIPS || purpose == DVIPDFM)
2814 if (purpose == DVIPS || purpose == DVIPDFM)
2818 if (purpose == DVIPS || purpose == DVIPDFM)
2822 if (purpose == DVIPS || purpose == DVIPDFM)
2826 // dvipdfm does not know this
2827 if (purpose == DVIPDFM)
2831 if (purpose == DVIPDFM)
2835 if (purpose == DVIPS || purpose == DVIPDFM)
2839 if (purpose == DVIPS || purpose == DVIPDFM)
2843 if (purpose == DVIPS || purpose == DVIPDFM)
2847 if (purpose == DVIPS || purpose == DVIPDFM)
2851 if (purpose == DVIPS || purpose == DVIPDFM)
2855 if (purpose == DVIPS || purpose == DVIPDFM)
2859 if (purpose == DVIPS || purpose == DVIPDFM)
2863 if (purpose == DVIPS || purpose == DVIPDFM)
2867 if (purpose == DVIPS || purpose == DVIPDFM)
2871 if (purpose == DVIPS || purpose == DVIPDFM)
2875 if (purpose == DVIPS || purpose == DVIPDFM)
2879 if (purpose == DVIPS || purpose == DVIPDFM)
2883 if (purpose == DVIPS || purpose == DVIPDFM)
2887 if (purpose == DVIPS || purpose == DVIPDFM)
2891 if (purpose == DVIPS || purpose == DVIPDFM)
2894 case PAPER_USEXECUTIVE:
2895 // dvipdfm does not know this
2896 if (purpose == DVIPDFM)
2901 case PAPER_USLETTER:
2903 if (purpose == XDVI)
2910 string const BufferParams::dvips_options() const
2914 // If the class loads the geometry package, we do not know which
2915 // paper size is used, since we do not set it (bug 7013).
2916 // Therefore we must not specify any argument here.
2917 // dvips gets the correct paper size via DVI specials in this case
2918 // (if the class uses the geometry package correctly).
2919 if (documentClass().provides("geometry"))
2923 && papersize == PAPER_CUSTOM
2924 && !lyxrc.print_paper_dimension_flag.empty()
2925 && !paperwidth.empty()
2926 && !paperheight.empty()) {
2927 // using a custom papersize
2928 result = lyxrc.print_paper_dimension_flag;
2929 result += ' ' + paperwidth;
2930 result += ',' + paperheight;
2932 string const paper_option = paperSizeName(DVIPS);
2933 if (!paper_option.empty() && (paper_option != "letter" ||
2934 orientation != ORIENTATION_LANDSCAPE)) {
2935 // dvips won't accept -t letter -t landscape.
2936 // In all other cases, include the paper size
2938 result = lyxrc.print_paper_flag;
2939 result += ' ' + paper_option;
2942 if (orientation == ORIENTATION_LANDSCAPE &&
2943 papersize != PAPER_CUSTOM)
2944 result += ' ' + lyxrc.print_landscape_flag;
2949 string const BufferParams::font_encoding() const
2951 return font_encodings().empty() ? "default" : font_encodings().back();
2955 vector<string> const BufferParams::font_encodings() const
2957 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2959 vector<string> fontencs;
2961 // "default" means "no explicit font encoding"
2962 if (doc_fontenc != "default") {
2963 fontencs = getVectorFromString(doc_fontenc);
2964 if (!language->fontenc().empty()
2965 && ascii_lowercase(language->fontenc()) != "none") {
2966 vector<string> fencs = getVectorFromString(language->fontenc());
2967 vector<string>::const_iterator fit = fencs.begin();
2968 for (; fit != fencs.end(); ++fit) {
2969 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2970 fontencs.push_back(*fit);
2979 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2981 // suppress the babel call if there is no BabelName defined
2982 // for the document language in the lib/languages file and if no
2983 // other languages are used (lang_opts is then empty)
2984 if (lang_opts.empty())
2986 // either a specific language (AsBabelOptions setting in
2987 // lib/languages) or the prefs require the languages to
2988 // be submitted to babel itself (not the class).
2990 return "\\usepackage[" + lang_opts + "]{babel}";
2991 return "\\usepackage{babel}";
2995 docstring BufferParams::getGraphicsDriver(string const & package) const
2999 if (package == "geometry") {
3000 if (graphics_driver == "dvips"
3001 || graphics_driver == "dvipdfm"
3002 || graphics_driver == "pdftex"
3003 || graphics_driver == "vtex")
3004 result = from_ascii(graphics_driver);
3005 else if (graphics_driver == "dvipdfmx")
3006 result = from_ascii("dvipdfm");
3013 void BufferParams::writeEncodingPreamble(otexstream & os,
3014 LaTeXFeatures & features) const
3016 // XeTeX/LuaTeX: (see also #9740)
3017 // With Unicode fonts we use utf8-plain without encoding package.
3018 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
3019 // XeTeX must use ASCII encoding (see Buffer.cpp),
3020 // for LuaTeX, we load "luainputenc" (see below).
3021 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
3024 if (inputenc == "auto") {
3025 string const doc_encoding =
3026 language->encoding()->latexName();
3027 Encoding::Package const package =
3028 language->encoding()->package();
3030 // Create list of inputenc options:
3031 set<string> encodings;
3032 // luainputenc fails with more than one encoding
3033 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
3034 // list all input encodings used in the document
3035 encodings = features.getEncodingSet(doc_encoding);
3037 // If the "japanese" package (i.e. pLaTeX) is used,
3038 // inputenc must be omitted.
3039 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
3040 if ((!encodings.empty() || package == Encoding::inputenc)
3041 && !features.isRequired("japanese")
3042 && !features.isProvided("inputenc")) {
3043 os << "\\usepackage[";
3044 set<string>::const_iterator it = encodings.begin();
3045 set<string>::const_iterator const end = encodings.end();
3047 os << from_ascii(*it);
3050 for (; it != end; ++it)
3051 os << ',' << from_ascii(*it);
3052 if (package == Encoding::inputenc) {
3053 if (!encodings.empty())
3055 os << from_ascii(doc_encoding);
3057 if (features.runparams().flavor == OutputParams::LUATEX
3058 || features.runparams().flavor == OutputParams::DVILUATEX)
3059 os << "]{luainputenc}\n";
3061 os << "]{inputenc}\n";
3063 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3064 if (language->encoding()->name() == "utf8-cjk"
3065 && LaTeXFeatures::isAvailable("CJKutf8"))
3066 os << "\\usepackage{CJKutf8}\n";
3068 os << "\\usepackage{CJK}\n";
3070 } else if (inputenc != "default") {
3071 switch (encoding().package()) {
3072 case Encoding::none:
3073 case Encoding::japanese:
3075 case Encoding::inputenc:
3076 // do not load inputenc if japanese is used
3077 // or if the class provides inputenc
3078 if (features.isRequired("japanese")
3079 || features.isProvided("inputenc"))
3081 os << "\\usepackage[" << from_ascii(encoding().latexName());
3082 if (features.runparams().flavor == OutputParams::LUATEX
3083 || features.runparams().flavor == OutputParams::DVILUATEX)
3084 os << "]{luainputenc}\n";
3086 os << "]{inputenc}\n";
3089 if (encoding().name() == "utf8-cjk"
3090 && LaTeXFeatures::isAvailable("CJKutf8"))
3091 os << "\\usepackage{CJKutf8}\n";
3093 os << "\\usepackage{CJK}\n";
3096 // Load the CJK package if needed by a secondary language.
3097 // If the main encoding is some variant of UTF8, use CJKutf8.
3098 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3099 if (encoding().iconvName() == "UTF-8"
3100 && LaTeXFeatures::isAvailable("CJKutf8"))
3101 os << "\\usepackage{CJKutf8}\n";
3103 os << "\\usepackage{CJK}\n";
3109 string const BufferParams::parseFontName(string const & name) const
3111 string mangled = name;
3112 size_t const idx = mangled.find('[');
3113 if (idx == string::npos || idx == 0)
3116 return mangled.substr(0, idx - 1);
3120 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3122 if (fontsRoman() == "default" && fontsSans() == "default"
3123 && fontsTypewriter() == "default"
3124 && (fontsMath() == "default" || fontsMath() == "auto"))
3130 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3131 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3132 * Mapping=tex-text option assures TeX ligatures (such as "--")
3133 * are resolved. Note that tt does not use these ligatures.
3135 * -- add more GUI options?
3136 * -- add more fonts (fonts for other scripts)
3137 * -- if there's a way to find out if a font really supports
3138 * OldStyle, enable/disable the widget accordingly.
3140 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3141 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3142 // However, until v.2 (2010/07/11) fontspec only knew
3143 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3144 // was introduced for both XeTeX and LuaTeX (LuaTeX
3145 // didn't understand "Mapping=tex-text", while XeTeX
3146 // understood both. With most recent versions, both
3147 // variants are understood by both engines. However,
3148 // we want to provide support for at least TeXLive 2009
3149 // (for XeTeX; LuaTeX is only supported as of v.2)
3150 string const texmapping =
3151 (features.runparams().flavor == OutputParams::XETEX) ?
3152 "Mapping=tex-text" : "Ligatures=TeX";
3153 if (fontsRoman() != "default") {
3154 os << "\\setmainfont[" << texmapping;
3155 if (fonts_old_figures)
3156 os << ",Numbers=OldStyle";
3157 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3159 if (fontsSans() != "default") {
3160 string const sans = parseFontName(fontsSans());
3161 if (fontsSansScale() != 100)
3162 os << "\\setsansfont[Scale="
3163 << float(fontsSansScale()) / 100
3164 << "," << texmapping << "]{"
3167 os << "\\setsansfont[" << texmapping << "]{"
3170 if (fontsTypewriter() != "default") {
3171 string const mono = parseFontName(fontsTypewriter());
3172 if (fontsTypewriterScale() != 100)
3173 os << "\\setmonofont[Scale="
3174 << float(fontsTypewriterScale()) / 100
3178 os << "\\setmonofont{"
3185 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3186 bool const dryrun = features.runparams().dryrun;
3187 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3188 bool const nomath = (fontsMath() == "default");
3191 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3192 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3196 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3197 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3198 nomath, fontsSansScale());
3200 // MONOSPACED/TYPEWRITER
3201 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3202 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3203 nomath, fontsTypewriterScale());
3206 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3207 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3214 Encoding const & BufferParams::encoding() const
3216 // Main encoding for LaTeX output.
3218 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3219 // As the "flavor" is only known once export started, this
3220 // cannot be handled here. Instead, runparams.encoding is set
3221 // to ASCII in Buffer::makeLaTeXFile (for export)
3222 // and Buffer::writeLaTeXSource (for preview).
3224 return *(encodings.fromLyXName("utf8-plain"));
3225 if (inputenc == "auto" || inputenc == "default")
3226 return *language->encoding();
3227 Encoding const * const enc = encodings.fromLyXName(inputenc);
3230 LYXERR0("Unknown inputenc value `" << inputenc
3231 << "'. Using `auto' instead.");
3232 return *language->encoding();
3236 bool BufferParams::addCiteEngine(string const & engine)
3238 LayoutModuleList::const_iterator it = cite_engine_.begin();
3239 LayoutModuleList::const_iterator en = cite_engine_.end();
3240 for (; it != en; ++it)
3243 cite_engine_.push_back(engine);
3248 bool BufferParams::addCiteEngine(vector<string> const & engine)
3250 vector<string>::const_iterator it = engine.begin();
3251 vector<string>::const_iterator en = engine.end();
3253 for (; it != en; ++it)
3254 if (!addCiteEngine(*it))
3260 string const & BufferParams::defaultBiblioStyle() const
3262 return documentClass().defaultBiblioStyle();
3266 bool const & BufferParams::fullAuthorList() const
3268 return documentClass().fullAuthorList();
3272 void BufferParams::setCiteEngine(string const & engine)
3275 addCiteEngine(engine);
3279 void BufferParams::setCiteEngine(vector<string> const & engine)
3282 addCiteEngine(engine);
3286 vector<string> BufferParams::citeCommands() const
3288 static CitationStyle const default_style;
3289 vector<string> commands =
3290 documentClass().citeCommands(citeEngineType());
3291 if (commands.empty())
3292 commands.push_back(default_style.cmd);
3297 vector<CitationStyle> BufferParams::citeStyles() const
3299 static CitationStyle const default_style;
3300 vector<CitationStyle> styles =
3301 documentClass().citeStyles(citeEngineType());
3303 styles.push_back(default_style);
3307 void BufferParams::invalidateConverterCache() const
3309 pimpl_->isExportCacheValid = false;
3310 pimpl_->isViewCacheValid = false;