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"
43 #include "PDFOptions.h"
45 #include "frontends/alert.h"
47 #include "insets/InsetListingsParams.h"
49 #include "support/convert.h"
50 #include "support/debug.h"
51 #include "support/docstream.h"
52 #include "support/FileName.h"
53 #include "support/filetools.h"
54 #include "support/gettext.h"
55 #include "support/Messages.h"
56 #include "support/mutex.h"
57 #include "support/Package.h"
58 #include "support/Translator.h"
59 #include "support/lstrings.h"
65 using namespace lyx::support;
68 static char const * const string_paragraph_separation[] = {
73 static char const * const string_quotes_language[] = {
74 "english", "swedish", "german", "polish", "french", "danish", ""
78 static char const * const string_papersize[] = {
79 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
80 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
81 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
82 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
83 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
88 static char const * const string_orientation[] = {
89 "portrait", "landscape", ""
93 static char const * const tex_graphics[] = {
94 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
95 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
96 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
97 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
108 // Paragraph separation
109 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
112 ParSepTranslator const init_parseptranslator()
114 ParSepTranslator translator
115 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
116 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
121 ParSepTranslator const & parseptranslator()
123 static ParSepTranslator const translator =
124 init_parseptranslator();
130 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
133 QuotesLangTranslator const init_quoteslangtranslator()
135 QuotesLangTranslator translator
136 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
137 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
138 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
139 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
140 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
141 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
146 QuotesLangTranslator const & quoteslangtranslator()
148 static QuotesLangTranslator const translator =
149 init_quoteslangtranslator();
155 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
158 static PaperSizeTranslator initPaperSizeTranslator()
160 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
161 translator.addPair(string_papersize[1], PAPER_CUSTOM);
162 translator.addPair(string_papersize[2], PAPER_USLETTER);
163 translator.addPair(string_papersize[3], PAPER_USLEGAL);
164 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
165 translator.addPair(string_papersize[5], PAPER_A0);
166 translator.addPair(string_papersize[6], PAPER_A1);
167 translator.addPair(string_papersize[7], PAPER_A2);
168 translator.addPair(string_papersize[8], PAPER_A3);
169 translator.addPair(string_papersize[9], PAPER_A4);
170 translator.addPair(string_papersize[10], PAPER_A5);
171 translator.addPair(string_papersize[11], PAPER_A6);
172 translator.addPair(string_papersize[12], PAPER_B0);
173 translator.addPair(string_papersize[13], PAPER_B1);
174 translator.addPair(string_papersize[14], PAPER_B2);
175 translator.addPair(string_papersize[15], PAPER_B3);
176 translator.addPair(string_papersize[16], PAPER_B4);
177 translator.addPair(string_papersize[17], PAPER_B5);
178 translator.addPair(string_papersize[18], PAPER_B6);
179 translator.addPair(string_papersize[19], PAPER_C0);
180 translator.addPair(string_papersize[20], PAPER_C1);
181 translator.addPair(string_papersize[21], PAPER_C2);
182 translator.addPair(string_papersize[22], PAPER_C3);
183 translator.addPair(string_papersize[23], PAPER_C4);
184 translator.addPair(string_papersize[24], PAPER_C5);
185 translator.addPair(string_papersize[25], PAPER_C6);
186 translator.addPair(string_papersize[26], PAPER_JISB0);
187 translator.addPair(string_papersize[27], PAPER_JISB1);
188 translator.addPair(string_papersize[28], PAPER_JISB2);
189 translator.addPair(string_papersize[29], PAPER_JISB3);
190 translator.addPair(string_papersize[30], PAPER_JISB4);
191 translator.addPair(string_papersize[31], PAPER_JISB5);
192 translator.addPair(string_papersize[32], PAPER_JISB6);
197 PaperSizeTranslator const & papersizetranslator()
199 static PaperSizeTranslator const translator =
200 initPaperSizeTranslator();
206 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
209 PaperOrientationTranslator const init_paperorientationtranslator()
211 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
212 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
217 PaperOrientationTranslator const & paperorientationtranslator()
219 static PaperOrientationTranslator const translator =
220 init_paperorientationtranslator();
226 typedef Translator<int, PageSides> SidesTranslator;
229 SidesTranslator const init_sidestranslator()
231 SidesTranslator translator(1, OneSide);
232 translator.addPair(2, TwoSides);
237 SidesTranslator const & sidestranslator()
239 static SidesTranslator const translator = init_sidestranslator();
245 typedef Translator<int, BufferParams::Package> PackageTranslator;
248 PackageTranslator const init_packagetranslator()
250 PackageTranslator translator(0, BufferParams::package_off);
251 translator.addPair(1, BufferParams::package_auto);
252 translator.addPair(2, BufferParams::package_on);
257 PackageTranslator const & packagetranslator()
259 static PackageTranslator const translator =
260 init_packagetranslator();
266 typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
269 CiteEngineTypeTranslator const init_citeenginetypetranslator()
271 CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
272 translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
273 translator.addPair("default", ENGINE_TYPE_DEFAULT);
278 CiteEngineTypeTranslator const & citeenginetypetranslator()
280 static CiteEngineTypeTranslator const translator =
281 init_citeenginetypetranslator();
287 typedef Translator<string, Spacing::Space> SpaceTranslator;
290 SpaceTranslator const init_spacetranslator()
292 SpaceTranslator translator("default", Spacing::Default);
293 translator.addPair("single", Spacing::Single);
294 translator.addPair("onehalf", Spacing::Onehalf);
295 translator.addPair("double", Spacing::Double);
296 translator.addPair("other", Spacing::Other);
301 SpaceTranslator const & spacetranslator()
303 static SpaceTranslator const translator = init_spacetranslator();
308 bool inSystemDir(FileName const & document_dir, string & system_dir)
310 // A document is assumed to be in a system LyX directory (not
311 // necessarily the system directory of the running instance)
312 // if both "configure.py" and "chkconfig.ltx" are found in
313 // either document_dir/../ or document_dir/../../.
314 // If true, the system directory path is returned in system_dir
315 // with a trailing path separator.
317 string const msg = "Checking whether document is in a system dir...";
319 string dir = document_dir.absFileName();
321 for (int i = 0; i < 2; ++i) {
322 dir = addPath(dir, "..");
323 if (!fileSearch(dir, "configure.py").empty() &&
324 !fileSearch(dir, "chkconfig.ltx").empty()) {
325 LYXERR(Debug::FILES, msg << " yes");
326 system_dir = addPath(FileName(dir).realPath(), "");
331 LYXERR(Debug::FILES, msg << " no");
332 system_dir = string();
339 class BufferParams::Impl
344 AuthorList authorlist;
345 BranchList branchlist;
346 Bullet temp_bullets[4];
347 Bullet user_defined_bullets[4];
348 IndicesList indiceslist;
350 /** This is the amount of space used for paragraph_separation "skip",
351 * and for detached paragraphs in "indented" documents.
355 PDFOptions pdfoptions;
356 LayoutFileIndex baseClass_;
357 FormatList exportableFormatList;
358 FormatList viewableFormatList;
359 bool isViewCacheValid;
360 bool isExportCacheValid;
364 BufferParams::Impl::Impl()
365 : defskip(VSpace::MEDSKIP), baseClass_(string("")),
366 isViewCacheValid(false), isExportCacheValid(false)
368 // set initial author
370 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
375 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
378 return new BufferParams::Impl(*ptr);
382 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
388 BufferParams::BufferParams()
391 setBaseClass(defaultBaseclass());
392 cite_engine_.push_back("basic");
393 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
395 paragraph_separation = ParagraphIndentSeparation;
396 quotes_language = InsetQuotes::EnglishQuotes;
397 fontsize = "default";
400 papersize = PAPER_DEFAULT;
401 orientation = ORIENTATION_PORTRAIT;
402 use_geometry = false;
403 biblio_style = "plain";
404 use_bibtopic = false;
406 save_transient_properties = true;
407 track_changes = false;
408 output_changes = false;
409 use_default_options = true;
410 maintain_unincluded_children = false;
413 language = default_language;
415 fonts_roman[0] = "default";
416 fonts_roman[1] = "default";
417 fonts_sans[0] = "default";
418 fonts_sans[1] = "default";
419 fonts_typewriter[0] = "default";
420 fonts_typewriter[1] = "default";
421 fonts_math[0] = "auto";
422 fonts_math[1] = "auto";
423 fonts_default_family = "default";
424 useNonTeXFonts = false;
425 fonts_expert_sc = false;
426 fonts_old_figures = false;
427 fonts_sans_scale[0] = 100;
428 fonts_sans_scale[1] = 100;
429 fonts_typewriter_scale[0] = 100;
430 fonts_typewriter_scale[1] = 100;
432 lang_package = "default";
433 graphics_driver = "default";
434 default_output_format = "default";
435 bibtex_command = "default";
436 index_command = "default";
439 listings_params = string();
440 pagestyle = "default";
441 suppress_date = false;
442 justification = true;
443 // no color is the default (white)
444 backgroundcolor = lyx::rgbFromHexName("#ffffff");
445 isbackgroundcolor = false;
446 // no color is the default (black)
447 fontcolor = lyx::rgbFromHexName("#000000");
449 // light gray is the default font color for greyed-out notes
450 notefontcolor = lyx::rgbFromHexName("#cccccc");
451 boxbgcolor = lyx::rgbFromHexName("#ff0000");
452 compressed = lyxrc.save_compressed;
453 for (int iter = 0; iter < 4; ++iter) {
454 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
455 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
458 indiceslist().addDefault(B_("Index"));
459 html_be_strict = false;
460 html_math_output = MathML;
461 html_math_img_scale = 1.0;
462 html_css_as_file = false;
463 display_pixel_ratio = 1.0;
468 // map current author
469 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
473 docstring BufferParams::B_(string const & l10n) const
475 LASSERT(language, return from_utf8(l10n));
476 return getMessages(language->code()).get(l10n);
480 BufferParams::Package BufferParams::use_package(std::string const & p) const
482 PackageMap::const_iterator it = use_packages.find(p);
483 if (it == use_packages.end())
489 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
495 map<string, string> const & BufferParams::auto_packages()
497 static map<string, string> packages;
498 if (packages.empty()) {
499 // We could have a race condition here that two threads
500 // discover an empty map at the same time and want to fill
501 // it, but that is no problem, since the same contents is
502 // filled in twice then. Having the locker inside the
503 // packages.empty() condition has the advantage that we
504 // don't need the mutex overhead for simple reading.
506 Mutex::Locker locker(&mutex);
507 // adding a package here implies a file format change!
508 packages["amsmath"] =
509 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
510 packages["amssymb"] =
511 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
513 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
515 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
516 packages["mathdots"] =
517 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
518 packages["mathtools"] =
519 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
521 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
522 packages["stackrel"] =
523 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
524 packages["stmaryrd"] =
525 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");
526 packages["undertilde"] =
527 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
533 AuthorList & BufferParams::authors()
535 return pimpl_->authorlist;
539 AuthorList const & BufferParams::authors() const
541 return pimpl_->authorlist;
545 void BufferParams::addAuthor(Author a)
547 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
551 BranchList & BufferParams::branchlist()
553 return pimpl_->branchlist;
557 BranchList const & BufferParams::branchlist() const
559 return pimpl_->branchlist;
563 IndicesList & BufferParams::indiceslist()
565 return pimpl_->indiceslist;
569 IndicesList const & BufferParams::indiceslist() const
571 return pimpl_->indiceslist;
575 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
577 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
578 return pimpl_->temp_bullets[index];
582 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
584 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
585 return pimpl_->temp_bullets[index];
589 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
591 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
592 return pimpl_->user_defined_bullets[index];
596 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
598 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
599 return pimpl_->user_defined_bullets[index];
603 Spacing & BufferParams::spacing()
605 return pimpl_->spacing;
609 Spacing const & BufferParams::spacing() const
611 return pimpl_->spacing;
615 PDFOptions & BufferParams::pdfoptions()
617 return pimpl_->pdfoptions;
621 PDFOptions const & BufferParams::pdfoptions() const
623 return pimpl_->pdfoptions;
627 HSpace const & BufferParams::getIndentation() const
629 return pimpl_->indentation;
633 void BufferParams::setIndentation(HSpace const & indent)
635 pimpl_->indentation = indent;
639 VSpace const & BufferParams::getDefSkip() const
641 return pimpl_->defskip;
645 void BufferParams::setDefSkip(VSpace const & vs)
647 // DEFSKIP will cause an infinite loop
648 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
649 pimpl_->defskip = vs;
653 string BufferParams::readToken(Lexer & lex, string const & token,
654 FileName const & filepath)
658 if (token == "\\textclass") {
660 string const classname = lex.getString();
661 // if there exists a local layout file, ignore the system one
662 // NOTE: in this case, the textclass (.cls file) is assumed to
665 LayoutFileList & bcl = LayoutFileList::get();
666 if (!filepath.empty()) {
667 // If classname is an absolute path, the document is
668 // using a local layout file which could not be accessed
669 // by a relative path. In this case the path is correct
670 // even if the document was moved to a different
671 // location. However, we will have a problem if the
672 // document was generated on a different platform.
673 bool isabsolute = FileName::isAbsolute(classname);
674 string const classpath = onlyPath(classname);
675 string const path = isabsolute ? classpath
676 : FileName(addPath(filepath.absFileName(),
677 classpath)).realPath();
678 string const oldpath = isabsolute ? string()
679 : FileName(addPath(origin, classpath)).realPath();
680 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
682 // that returns non-empty if a "local" layout file is found.
684 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
685 from_utf8(filepath.absFileName())));
688 setBaseClass(onlyFileName(tcp));
690 setBaseClass(onlyFileName(classname));
691 // We assume that a tex class exists for local or unknown
692 // layouts so this warning, will only be given for system layouts.
693 if (!baseClass()->isTeXClassAvailable()) {
694 docstring const desc =
695 translateIfPossible(from_utf8(baseClass()->description()));
696 docstring const prereqs =
697 from_utf8(baseClass()->prerequisites());
698 docstring const msg =
699 bformat(_("The selected document class\n"
701 "requires external files that are not available.\n"
702 "The document class can still be used, but the\n"
703 "document cannot be compiled until the following\n"
704 "prerequisites are installed:\n"
706 "See section 3.1.2.2 (Class Availability) of the\n"
707 "User's Guide for more information."), desc, prereqs);
708 frontend::Alert::warning(_("Document class not available"),
711 } else if (token == "\\save_transient_properties") {
712 lex >> save_transient_properties;
713 } else if (token == "\\origin") {
715 origin = lex.getString();
716 string const sysdirprefix = "/systemlyxdir/";
717 if (prefixIs(origin, sysdirprefix)) {
719 if (inSystemDir(filepath, docsys))
720 origin.replace(0, sysdirprefix.length() - 1, docsys);
722 origin.replace(0, sysdirprefix.length() - 1,
723 package().system_support().absFileName());
725 } else if (token == "\\begin_preamble") {
727 } else if (token == "\\begin_local_layout") {
728 readLocalLayout(lex, false);
729 } else if (token == "\\begin_forced_local_layout") {
730 readLocalLayout(lex, true);
731 } else if (token == "\\begin_modules") {
733 } else if (token == "\\begin_removed_modules") {
734 readRemovedModules(lex);
735 } else if (token == "\\begin_includeonly") {
736 readIncludeonly(lex);
737 } else if (token == "\\maintain_unincluded_children") {
738 lex >> maintain_unincluded_children;
739 } else if (token == "\\options") {
741 options = lex.getString();
742 } else if (token == "\\use_default_options") {
743 lex >> use_default_options;
744 } else if (token == "\\master") {
746 master = lex.getString();
747 if (!filepath.empty() && FileName::isAbsolute(origin)) {
748 bool const isabs = FileName::isAbsolute(master);
749 FileName const abspath(isabs ? master : origin + master);
750 bool const moved = filepath != FileName(origin);
751 if (moved && abspath.exists()) {
752 docstring const path = isabs
754 : from_utf8(abspath.realPath());
755 docstring const refpath =
756 from_utf8(filepath.absFileName());
757 master = to_utf8(makeRelPath(path, refpath));
760 } else if (token == "\\suppress_date") {
761 lex >> suppress_date;
762 } else if (token == "\\justification") {
763 lex >> justification;
764 } else if (token == "\\language") {
766 } else if (token == "\\language_package") {
768 lang_package = lex.getString();
769 } else if (token == "\\inputencoding") {
771 } else if (token == "\\graphics") {
772 readGraphicsDriver(lex);
773 } else if (token == "\\default_output_format") {
774 lex >> default_output_format;
775 } else if (token == "\\bibtex_command") {
777 bibtex_command = lex.getString();
778 } else if (token == "\\index_command") {
780 index_command = lex.getString();
781 } else if (token == "\\fontencoding") {
783 fontenc = lex.getString();
784 } else if (token == "\\font_roman") {
785 lex >> fonts_roman[0];
786 lex >> fonts_roman[1];
787 } else if (token == "\\font_sans") {
788 lex >> fonts_sans[0];
789 lex >> fonts_sans[1];
790 } else if (token == "\\font_typewriter") {
791 lex >> fonts_typewriter[0];
792 lex >> fonts_typewriter[1];
793 } else if (token == "\\font_math") {
794 lex >> fonts_math[0];
795 lex >> fonts_math[1];
796 } else if (token == "\\font_default_family") {
797 lex >> fonts_default_family;
798 } else if (token == "\\use_non_tex_fonts") {
799 lex >> useNonTeXFonts;
800 } else if (token == "\\font_sc") {
801 lex >> fonts_expert_sc;
802 } else if (token == "\\font_osf") {
803 lex >> fonts_old_figures;
804 } else if (token == "\\font_sf_scale") {
805 lex >> fonts_sans_scale[0];
806 lex >> fonts_sans_scale[1];
807 } else if (token == "\\font_tt_scale") {
808 lex >> fonts_typewriter_scale[0];
809 lex >> fonts_typewriter_scale[1];
810 } else if (token == "\\font_cjk") {
812 } else if (token == "\\paragraph_separation") {
815 paragraph_separation = parseptranslator().find(parsep);
816 } else if (token == "\\paragraph_indentation") {
818 string indentation = lex.getString();
819 pimpl_->indentation = HSpace(indentation);
820 } else if (token == "\\defskip") {
822 string const defskip = lex.getString();
823 pimpl_->defskip = VSpace(defskip);
824 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
826 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
827 } else if (token == "\\quotes_language") {
830 quotes_language = quoteslangtranslator().find(quotes_lang);
831 } else if (token == "\\papersize") {
834 papersize = papersizetranslator().find(ppsize);
835 } else if (token == "\\use_geometry") {
837 } else if (token == "\\use_package") {
842 use_package(package, packagetranslator().find(use));
843 } else if (token == "\\cite_engine") {
845 vector<string> engine = getVectorFromString(lex.getString());
846 setCiteEngine(engine);
847 } else if (token == "\\cite_engine_type") {
850 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
851 } else if (token == "\\biblio_style") {
853 biblio_style = lex.getString();
854 } else if (token == "\\use_bibtopic") {
856 } else if (token == "\\use_indices") {
858 } else if (token == "\\tracking_changes") {
859 lex >> track_changes;
860 } else if (token == "\\output_changes") {
861 lex >> output_changes;
862 } else if (token == "\\branch") {
864 docstring branch = lex.getDocString();
865 branchlist().add(branch);
868 string const tok = lex.getString();
869 if (tok == "\\end_branch")
871 Branch * branch_ptr = branchlist().find(branch);
872 if (tok == "\\selected") {
875 branch_ptr->setSelected(lex.getInteger());
877 if (tok == "\\filename_suffix") {
880 branch_ptr->setFileNameSuffix(lex.getInteger());
882 if (tok == "\\color") {
884 string color = lex.getString();
886 branch_ptr->setColor(color);
887 // Update also the Color table:
889 color = lcolor.getX11Name(Color_background);
891 lcolor.setColor(to_utf8(branch), color);
894 } else if (token == "\\index") {
896 docstring index = lex.getDocString();
898 indiceslist().add(index);
901 string const tok = lex.getString();
902 if (tok == "\\end_index")
904 Index * index_ptr = indiceslist().find(index);
905 if (tok == "\\shortcut") {
907 shortcut = lex.getDocString();
909 index_ptr->setShortcut(shortcut);
911 if (tok == "\\color") {
913 string color = lex.getString();
915 index_ptr->setColor(color);
916 // Update also the Color table:
918 color = lcolor.getX11Name(Color_background);
920 if (!shortcut.empty())
921 lcolor.setColor(to_utf8(shortcut), color);
924 } else if (token == "\\author") {
926 istringstream ss(lex.getString());
930 } else if (token == "\\paperorientation") {
933 orientation = paperorientationtranslator().find(orient);
934 } else if (token == "\\backgroundcolor") {
936 backgroundcolor = lyx::rgbFromHexName(lex.getString());
937 isbackgroundcolor = true;
938 } else if (token == "\\fontcolor") {
940 fontcolor = lyx::rgbFromHexName(lex.getString());
942 } else if (token == "\\notefontcolor") {
944 string color = lex.getString();
945 notefontcolor = lyx::rgbFromHexName(color);
946 lcolor.setColor("notefontcolor", color);
947 } else if (token == "\\boxbgcolor") {
949 string color = lex.getString();
950 boxbgcolor = lyx::rgbFromHexName(color);
951 lcolor.setColor("boxbgcolor", color);
952 } else if (token == "\\paperwidth") {
954 } else if (token == "\\paperheight") {
956 } else if (token == "\\leftmargin") {
958 } else if (token == "\\topmargin") {
960 } else if (token == "\\rightmargin") {
962 } else if (token == "\\bottommargin") {
964 } else if (token == "\\headheight") {
966 } else if (token == "\\headsep") {
968 } else if (token == "\\footskip") {
970 } else if (token == "\\columnsep") {
972 } else if (token == "\\paperfontsize") {
974 } else if (token == "\\papercolumns") {
976 } else if (token == "\\listings_params") {
979 listings_params = InsetListingsParams(par).params();
980 } else if (token == "\\papersides") {
983 sides = sidestranslator().find(psides);
984 } else if (token == "\\paperpagestyle") {
986 } else if (token == "\\bullet") {
988 } else if (token == "\\bulletLaTeX") {
989 readBulletsLaTeX(lex);
990 } else if (token == "\\secnumdepth") {
992 } else if (token == "\\tocdepth") {
994 } else if (token == "\\spacing") {
998 if (nspacing == "other") {
1001 spacing().set(spacetranslator().find(nspacing), tmp_val);
1002 } else if (token == "\\float_placement") {
1003 lex >> float_placement;
1005 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
1006 string toktmp = pdfoptions().readToken(lex, token);
1007 if (!toktmp.empty()) {
1008 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
1012 } else if (token == "\\html_math_output") {
1015 html_math_output = static_cast<MathOutput>(temp);
1016 } else if (token == "\\html_be_strict") {
1017 lex >> html_be_strict;
1018 } else if (token == "\\html_css_as_file") {
1019 lex >> html_css_as_file;
1020 } else if (token == "\\html_math_img_scale") {
1021 lex >> html_math_img_scale;
1022 } else if (token == "\\html_latex_start") {
1024 html_latex_start = lex.getString();
1025 } else if (token == "\\html_latex_end") {
1027 html_latex_end = lex.getString();
1028 } else if (token == "\\output_sync") {
1030 } else if (token == "\\output_sync_macro") {
1031 lex >> output_sync_macro;
1032 } else if (token == "\\use_refstyle") {
1033 lex >> use_refstyle;
1035 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1045 // Quote argument if it contains spaces
1046 string quoteIfNeeded(string const & str) {
1047 if (contains(str, ' '))
1048 return "\"" + str + "\"";
1054 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1056 // The top of the file is written by the buffer.
1057 // Prints out the buffer info into the .lyx file given by file
1059 os << "\\save_transient_properties "
1060 << convert<string>(save_transient_properties) << '\n';
1062 // the document directory (must end with a path separator)
1063 // realPath() is used to resolve symlinks, while addPath(..., "")
1064 // ensures a trailing path separator.
1066 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1067 string const sysdir = inSystemDir(FileName(filepath), docsys) ? docsys
1068 : addPath(package().system_support().realPath(), "");
1069 string const relpath =
1070 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1071 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1072 filepath = addPath("/systemlyxdir", relpath);
1073 else if (!save_transient_properties || !lyxrc.save_origin)
1074 filepath = "unavailable";
1075 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1078 os << "\\textclass "
1079 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1080 baseClass()->name()), "layout"))
1083 // then the preamble
1084 if (!preamble.empty()) {
1085 // remove '\n' from the end of preamble
1086 string const tmppreamble = rtrim(preamble, "\n");
1087 os << "\\begin_preamble\n"
1089 << "\n\\end_preamble\n";
1093 if (!options.empty()) {
1094 os << "\\options " << options << '\n';
1097 // use the class options defined in the layout?
1098 os << "\\use_default_options "
1099 << convert<string>(use_default_options) << "\n";
1101 // the master document
1102 if (!master.empty()) {
1103 os << "\\master " << master << '\n';
1107 if (!removed_modules_.empty()) {
1108 os << "\\begin_removed_modules" << '\n';
1109 list<string>::const_iterator it = removed_modules_.begin();
1110 list<string>::const_iterator en = removed_modules_.end();
1111 for (; it != en; ++it)
1113 os << "\\end_removed_modules" << '\n';
1117 if (!layout_modules_.empty()) {
1118 os << "\\begin_modules" << '\n';
1119 LayoutModuleList::const_iterator it = layout_modules_.begin();
1120 LayoutModuleList::const_iterator en = layout_modules_.end();
1121 for (; it != en; ++it)
1123 os << "\\end_modules" << '\n';
1127 if (!included_children_.empty()) {
1128 os << "\\begin_includeonly" << '\n';
1129 list<string>::const_iterator it = included_children_.begin();
1130 list<string>::const_iterator en = included_children_.end();
1131 for (; it != en; ++it)
1133 os << "\\end_includeonly" << '\n';
1135 os << "\\maintain_unincluded_children "
1136 << convert<string>(maintain_unincluded_children) << '\n';
1138 // local layout information
1139 string const local_layout = getLocalLayout(false);
1140 if (!local_layout.empty()) {
1141 // remove '\n' from the end
1142 string const tmplocal = rtrim(local_layout, "\n");
1143 os << "\\begin_local_layout\n"
1145 << "\n\\end_local_layout\n";
1147 string const forced_local_layout = getLocalLayout(true);
1148 if (!forced_local_layout.empty()) {
1149 // remove '\n' from the end
1150 string const tmplocal = rtrim(forced_local_layout, "\n");
1151 os << "\\begin_forced_local_layout\n"
1153 << "\n\\end_forced_local_layout\n";
1156 // then the text parameters
1157 if (language != ignore_language)
1158 os << "\\language " << language->lang() << '\n';
1159 os << "\\language_package " << lang_package
1160 << "\n\\inputencoding " << inputenc
1161 << "\n\\fontencoding " << fontenc
1162 << "\n\\font_roman \"" << fonts_roman[0]
1163 << "\" \"" << fonts_roman[1] << '"'
1164 << "\n\\font_sans \"" << fonts_sans[0]
1165 << "\" \"" << fonts_sans[1] << '"'
1166 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1167 << "\" \"" << fonts_typewriter[1] << '"'
1168 << "\n\\font_math \"" << fonts_math[0]
1169 << "\" \"" << fonts_math[1] << '"'
1170 << "\n\\font_default_family " << fonts_default_family
1171 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1172 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1173 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1174 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1175 << ' ' << fonts_sans_scale[1]
1176 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1177 << ' ' << fonts_typewriter_scale[1]
1179 if (!fonts_cjk.empty()) {
1180 os << "\\font_cjk " << fonts_cjk << '\n';
1182 os << "\\graphics " << graphics_driver << '\n';
1183 os << "\\default_output_format " << default_output_format << '\n';
1184 os << "\\output_sync " << output_sync << '\n';
1185 if (!output_sync_macro.empty())
1186 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1187 os << "\\bibtex_command " << bibtex_command << '\n';
1188 os << "\\index_command " << index_command << '\n';
1190 if (!float_placement.empty()) {
1191 os << "\\float_placement " << float_placement << '\n';
1193 os << "\\paperfontsize " << fontsize << '\n';
1195 spacing().writeFile(os);
1196 pdfoptions().writeFile(os);
1198 os << "\\papersize " << string_papersize[papersize]
1199 << "\n\\use_geometry " << convert<string>(use_geometry);
1200 map<string, string> const & packages = auto_packages();
1201 for (map<string, string>::const_iterator it = packages.begin();
1202 it != packages.end(); ++it)
1203 os << "\n\\use_package " << it->first << ' '
1204 << use_package(it->first);
1206 os << "\n\\cite_engine ";
1208 if (!cite_engine_.empty()) {
1209 LayoutModuleList::const_iterator be = cite_engine_.begin();
1210 LayoutModuleList::const_iterator en = cite_engine_.end();
1211 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1220 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1221 << "\n\\biblio_style " << biblio_style
1222 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1223 << "\n\\use_indices " << convert<string>(use_indices)
1224 << "\n\\paperorientation " << string_orientation[orientation]
1225 << "\n\\suppress_date " << convert<string>(suppress_date)
1226 << "\n\\justification " << convert<string>(justification)
1227 << "\n\\use_refstyle " << use_refstyle
1229 if (isbackgroundcolor == true)
1230 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1231 if (isfontcolor == true)
1232 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1233 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1234 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1235 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1236 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1238 BranchList::const_iterator it = branchlist().begin();
1239 BranchList::const_iterator end = branchlist().end();
1240 for (; it != end; ++it) {
1241 os << "\\branch " << to_utf8(it->branch())
1242 << "\n\\selected " << it->isSelected()
1243 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1244 << "\n\\color " << lyx::X11hexname(it->color())
1249 IndicesList::const_iterator iit = indiceslist().begin();
1250 IndicesList::const_iterator iend = indiceslist().end();
1251 for (; iit != iend; ++iit) {
1252 os << "\\index " << to_utf8(iit->index())
1253 << "\n\\shortcut " << to_utf8(iit->shortcut())
1254 << "\n\\color " << lyx::X11hexname(iit->color())
1259 if (!paperwidth.empty())
1260 os << "\\paperwidth "
1261 << VSpace(paperwidth).asLyXCommand() << '\n';
1262 if (!paperheight.empty())
1263 os << "\\paperheight "
1264 << VSpace(paperheight).asLyXCommand() << '\n';
1265 if (!leftmargin.empty())
1266 os << "\\leftmargin "
1267 << VSpace(leftmargin).asLyXCommand() << '\n';
1268 if (!topmargin.empty())
1269 os << "\\topmargin "
1270 << VSpace(topmargin).asLyXCommand() << '\n';
1271 if (!rightmargin.empty())
1272 os << "\\rightmargin "
1273 << VSpace(rightmargin).asLyXCommand() << '\n';
1274 if (!bottommargin.empty())
1275 os << "\\bottommargin "
1276 << VSpace(bottommargin).asLyXCommand() << '\n';
1277 if (!headheight.empty())
1278 os << "\\headheight "
1279 << VSpace(headheight).asLyXCommand() << '\n';
1280 if (!headsep.empty())
1282 << VSpace(headsep).asLyXCommand() << '\n';
1283 if (!footskip.empty())
1285 << VSpace(footskip).asLyXCommand() << '\n';
1286 if (!columnsep.empty())
1287 os << "\\columnsep "
1288 << VSpace(columnsep).asLyXCommand() << '\n';
1289 os << "\\secnumdepth " << secnumdepth
1290 << "\n\\tocdepth " << tocdepth
1291 << "\n\\paragraph_separation "
1292 << string_paragraph_separation[paragraph_separation];
1293 if (!paragraph_separation)
1294 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1296 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1297 os << "\n\\quotes_language "
1298 << string_quotes_language[quotes_language]
1299 << "\n\\papercolumns " << columns
1300 << "\n\\papersides " << sides
1301 << "\n\\paperpagestyle " << pagestyle << '\n';
1302 if (!listings_params.empty())
1303 os << "\\listings_params \"" <<
1304 InsetListingsParams(listings_params).encodedString() << "\"\n";
1305 for (int i = 0; i < 4; ++i) {
1306 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1307 if (user_defined_bullet(i).getFont() != -1) {
1308 os << "\\bullet " << i << " "
1309 << user_defined_bullet(i).getFont() << " "
1310 << user_defined_bullet(i).getCharacter() << " "
1311 << user_defined_bullet(i).getSize() << "\n";
1315 os << "\\bulletLaTeX " << i << " \""
1316 << lyx::to_ascii(user_defined_bullet(i).getText())
1322 os << "\\tracking_changes "
1323 << (save_transient_properties ? convert<string>(track_changes) : "false")
1326 os << "\\output_changes "
1327 << (save_transient_properties ? convert<string>(output_changes) : "false")
1330 os << "\\html_math_output " << html_math_output << '\n'
1331 << "\\html_css_as_file " << html_css_as_file << '\n'
1332 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1334 if (html_math_img_scale != 1.0)
1335 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1336 if (!html_latex_start.empty())
1337 os << "\\html_latex_start " << html_latex_start << '\n';
1338 if (!html_latex_end.empty())
1339 os << "\\html_latex_end " << html_latex_end << '\n';
1341 os << pimpl_->authorlist;
1345 void BufferParams::validate(LaTeXFeatures & features) const
1347 features.require(documentClass().requires());
1349 if (columns > 1 && language->rightToLeft())
1350 features.require("rtloutputdblcol");
1352 if (output_changes) {
1353 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1354 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1355 LaTeXFeatures::isAvailable("xcolor");
1357 switch (features.runparams().flavor) {
1358 case OutputParams::LATEX:
1359 case OutputParams::DVILUATEX:
1361 features.require("ct-dvipost");
1362 features.require("dvipost");
1363 } else if (xcolorulem) {
1364 features.require("ct-xcolor-ulem");
1365 features.require("ulem");
1366 features.require("xcolor");
1368 features.require("ct-none");
1371 case OutputParams::LUATEX:
1372 case OutputParams::PDFLATEX:
1373 case OutputParams::XETEX:
1375 features.require("ct-xcolor-ulem");
1376 features.require("ulem");
1377 features.require("xcolor");
1378 // improves color handling in PDF output
1379 features.require("pdfcolmk");
1381 features.require("ct-none");
1389 // Floats with 'Here definitely' as default setting.
1390 if (float_placement.find('H') != string::npos)
1391 features.require("float");
1393 for (PackageMap::const_iterator it = use_packages.begin();
1394 it != use_packages.end(); ++it) {
1395 if (it->first == "amsmath") {
1396 // AMS Style is at document level
1397 if (it->second == package_on ||
1398 features.isProvided("amsmath"))
1399 features.require(it->first);
1400 } else if (it->second == package_on)
1401 features.require(it->first);
1404 // Document-level line spacing
1405 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1406 features.require("setspace");
1408 // the bullet shapes are buffer level not paragraph level
1409 // so they are tested here
1410 for (int i = 0; i < 4; ++i) {
1411 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1413 int const font = user_defined_bullet(i).getFont();
1415 int const c = user_defined_bullet(i).getCharacter();
1421 features.require("latexsym");
1423 } else if (font == 1) {
1424 features.require("amssymb");
1425 } else if (font >= 2 && font <= 5) {
1426 features.require("pifont");
1430 if (pdfoptions().use_hyperref) {
1431 features.require("hyperref");
1432 // due to interferences with babel and hyperref, the color package has to
1433 // be loaded after hyperref when hyperref is used with the colorlinks
1434 // option, see http://www.lyx.org/trac/ticket/5291
1435 if (pdfoptions().colorlinks)
1436 features.require("color");
1438 if (!listings_params.empty()) {
1439 // do not test validity because listings_params is
1440 // supposed to be valid
1442 InsetListingsParams(listings_params).separatedParams(true);
1443 // we can't support all packages, but we should load the color package
1444 if (par.find("\\color", 0) != string::npos)
1445 features.require("color");
1448 // some languages are only available via polyglossia
1449 if (features.hasPolyglossiaExclusiveLanguages())
1450 features.require("polyglossia");
1452 if (useNonTeXFonts && fontsMath() != "auto")
1453 features.require("unicode-math");
1455 if (!language->requires().empty())
1456 features.require(language->requires());
1460 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1461 FileName const & filepath) const
1463 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1464 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1465 // \RequirePackage to do so, rather than the normal \usepackage
1466 // Do not try to load any other package before the document class, unless you
1467 // have a thorough understanding of the LATEX internals and know exactly what you
1469 if (features.mustProvide("fix-cm"))
1470 os << "\\RequirePackage{fix-cm}\n";
1471 // Likewise for fixltx2e. If other packages conflict with this policy,
1472 // treat it as a package bug (and report it!)
1473 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1474 if (features.mustProvide("fixltx2e"))
1475 os << "\\RequirePackage{fixltx2e}\n";
1477 os << "\\documentclass";
1479 DocumentClass const & tclass = documentClass();
1481 ostringstream clsoptions; // the document class options.
1483 if (tokenPos(tclass.opt_fontsize(),
1484 '|', fontsize) >= 0) {
1485 // only write if existing in list (and not default)
1486 clsoptions << fontsize << "pt,";
1489 // all paper sizes except of A4, A5, B5 and the US sizes need the
1491 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1492 && papersize != PAPER_USLETTER
1493 && papersize != PAPER_USLEGAL
1494 && papersize != PAPER_USEXECUTIVE
1495 && papersize != PAPER_A4
1496 && papersize != PAPER_A5
1497 && papersize != PAPER_B5;
1499 if (!use_geometry) {
1500 switch (papersize) {
1502 clsoptions << "a4paper,";
1504 case PAPER_USLETTER:
1505 clsoptions << "letterpaper,";
1508 clsoptions << "a5paper,";
1511 clsoptions << "b5paper,";
1513 case PAPER_USEXECUTIVE:
1514 clsoptions << "executivepaper,";
1517 clsoptions << "legalpaper,";
1551 if (sides != tclass.sides()) {
1554 clsoptions << "oneside,";
1557 clsoptions << "twoside,";
1563 if (columns != tclass.columns()) {
1565 clsoptions << "twocolumn,";
1567 clsoptions << "onecolumn,";
1571 && orientation == ORIENTATION_LANDSCAPE)
1572 clsoptions << "landscape,";
1574 // language should be a parameter to \documentclass
1575 if (language->babel() == "hebrew"
1576 && default_language->babel() != "hebrew")
1577 // This seems necessary
1578 features.useLanguage(default_language);
1580 ostringstream language_options;
1581 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1582 bool const use_polyglossia = features.usePolyglossia();
1583 bool const global = lyxrc.language_global_options;
1584 if (use_babel || (use_polyglossia && global)) {
1585 language_options << features.getBabelLanguages();
1586 if (!language->babel().empty()) {
1587 if (!language_options.str().empty())
1588 language_options << ',';
1589 language_options << language->babel();
1591 if (global && !features.needBabelLangOptions()
1592 && !language_options.str().empty())
1593 clsoptions << language_options.str() << ',';
1596 // the predefined options from the layout
1597 if (use_default_options && !tclass.options().empty())
1598 clsoptions << tclass.options() << ',';
1600 // the user-defined options
1601 if (!options.empty()) {
1602 clsoptions << options << ',';
1605 string strOptions(clsoptions.str());
1606 if (!strOptions.empty()) {
1607 strOptions = rtrim(strOptions, ",");
1609 os << '[' << from_utf8(strOptions) << ']';
1612 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1613 // end of \documentclass defs
1615 // if we use fontspec or newtxmath, we have to load the AMS packages here
1616 string const ams = features.loadAMSPackages();
1617 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1618 bool const use_newtxmath =
1619 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1620 ot1, false, false) == "newtxmath";
1621 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1622 os << from_ascii(ams);
1624 if (useNonTeXFonts) {
1625 if (!features.isProvided("fontspec"))
1626 os << "\\usepackage{fontspec}\n";
1627 if (features.mustProvide("unicode-math")
1628 && features.isAvailable("unicode-math"))
1629 os << "\\usepackage{unicode-math}\n";
1632 // font selection must be done before loading fontenc.sty
1633 string const fonts = loadFonts(features);
1635 os << from_utf8(fonts);
1637 if (fonts_default_family != "default")
1638 os << "\\renewcommand{\\familydefault}{\\"
1639 << from_ascii(fonts_default_family) << "}\n";
1641 // set font encoding
1642 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1643 if (!useNonTeXFonts && !features.isProvided("fontenc")
1644 && font_encoding() != "default") {
1645 // get main font encodings
1646 vector<string> fontencs = font_encodings();
1647 // get font encodings of secondary languages
1648 features.getFontEncodings(fontencs);
1649 if (!fontencs.empty()) {
1650 os << "\\usepackage["
1651 << from_ascii(getStringFromVector(fontencs))
1656 // handle inputenc etc.
1657 writeEncodingPreamble(os, features);
1660 if (!features.runparams().includeall && !included_children_.empty()) {
1661 os << "\\includeonly{";
1662 list<string>::const_iterator it = included_children_.begin();
1663 list<string>::const_iterator en = included_children_.end();
1665 for (; it != en; ++it) {
1666 string incfile = *it;
1667 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1668 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1670 if (!features.runparams().nice)
1672 // \includeonly doesn't want an extension
1673 incfile = changeExtension(incfile, string());
1674 incfile = support::latex_path(incfile);
1675 if (!incfile.empty()) {
1678 os << from_utf8(incfile);
1685 if (!features.isProvided("geometry")
1686 && (use_geometry || nonstandard_papersize)) {
1687 odocstringstream ods;
1688 if (!getGraphicsDriver("geometry").empty())
1689 ods << getGraphicsDriver("geometry");
1690 if (orientation == ORIENTATION_LANDSCAPE)
1691 ods << ",landscape";
1692 switch (papersize) {
1694 if (!paperwidth.empty())
1695 ods << ",paperwidth="
1696 << from_ascii(paperwidth);
1697 if (!paperheight.empty())
1698 ods << ",paperheight="
1699 << from_ascii(paperheight);
1701 case PAPER_USLETTER:
1702 ods << ",letterpaper";
1705 ods << ",legalpaper";
1707 case PAPER_USEXECUTIVE:
1708 ods << ",executivepaper";
1797 docstring const g_options = trim(ods.str(), ",");
1798 os << "\\usepackage";
1799 if (!g_options.empty())
1800 os << '[' << g_options << ']';
1801 os << "{geometry}\n";
1802 // output this only if use_geometry is true
1804 os << "\\geometry{verbose";
1805 if (!topmargin.empty())
1806 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1807 if (!bottommargin.empty())
1808 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1809 if (!leftmargin.empty())
1810 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1811 if (!rightmargin.empty())
1812 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1813 if (!headheight.empty())
1814 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1815 if (!headsep.empty())
1816 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1817 if (!footskip.empty())
1818 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1819 if (!columnsep.empty())
1820 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1823 } else if (orientation == ORIENTATION_LANDSCAPE
1824 || papersize != PAPER_DEFAULT) {
1825 features.require("papersize");
1828 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1829 if (pagestyle == "fancy")
1830 os << "\\usepackage{fancyhdr}\n";
1831 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1834 // only output when the background color is not default
1835 if (isbackgroundcolor == true) {
1836 // only require color here, the background color will be defined
1837 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1839 features.require("color");
1840 features.require("pagecolor");
1843 // only output when the font color is not default
1844 if (isfontcolor == true) {
1845 // only require color here, the font color will be defined
1846 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1848 features.require("color");
1849 features.require("fontcolor");
1852 // Only if class has a ToC hierarchy
1853 if (tclass.hasTocLevels()) {
1854 if (secnumdepth != tclass.secnumdepth()) {
1855 os << "\\setcounter{secnumdepth}{"
1859 if (tocdepth != tclass.tocdepth()) {
1860 os << "\\setcounter{tocdepth}{"
1866 if (paragraph_separation) {
1867 // when skip separation
1868 switch (getDefSkip().kind()) {
1869 case VSpace::SMALLSKIP:
1870 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1872 case VSpace::MEDSKIP:
1873 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1875 case VSpace::BIGSKIP:
1876 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1878 case VSpace::LENGTH:
1879 os << "\\setlength{\\parskip}{"
1880 << from_utf8(getDefSkip().length().asLatexString())
1883 default: // should never happen // Then delete it.
1884 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1887 os << "\\setlength{\\parindent}{0pt}\n";
1889 // when separation by indentation
1890 // only output something when a width is given
1891 if (getIndentation().asLyXCommand() != "default") {
1892 os << "\\setlength{\\parindent}{"
1893 << from_utf8(getIndentation().asLatexCommand())
1898 // Now insert the LyX specific LaTeX commands...
1899 docstring lyxpreamble;
1900 features.resolveAlternatives();
1903 if (!output_sync_macro.empty())
1904 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1905 else if (features.runparams().flavor == OutputParams::LATEX)
1906 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1907 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1908 lyxpreamble += "\\synctex=-1\n";
1911 // The package options (via \PassOptionsToPackage)
1912 lyxpreamble += from_ascii(features.getPackageOptions());
1914 // due to interferences with babel and hyperref, the color package has to
1915 // be loaded (when it is not already loaded) before babel when hyperref
1916 // is used with the colorlinks option, see
1917 // http://www.lyx.org/trac/ticket/5291
1918 // we decided therefore to load color always before babel, see
1919 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1920 lyxpreamble += from_ascii(features.getColorOptions());
1922 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1923 // we have to call babel before
1925 && (features.isRequired("jurabib")
1926 || features.isRequired("hyperref")
1927 || features.isRequired("varioref")
1928 || features.isRequired("vietnamese")
1929 || features.isRequired("japanese"))) {
1931 lyxpreamble += from_utf8(features.getBabelPresettings());
1932 lyxpreamble += from_utf8(babelCall(language_options.str(),
1933 features.needBabelLangOptions())) + '\n';
1934 lyxpreamble += from_utf8(features.getBabelPostsettings());
1937 // The optional packages;
1938 lyxpreamble += from_ascii(features.getPackages());
1940 // Additional Indices
1941 if (features.isRequired("splitidx")) {
1942 IndicesList::const_iterator iit = indiceslist().begin();
1943 IndicesList::const_iterator iend = indiceslist().end();
1944 for (; iit != iend; ++iit) {
1945 pair<docstring, docstring> indexname_latex =
1946 features.runparams().encoding->latexString(iit->index(),
1947 features.runparams().dryrun);
1948 if (!indexname_latex.second.empty()) {
1949 // issue a warning about omitted characters
1950 // FIXME: should be passed to the error dialog
1951 frontend::Alert::warning(_("Uncodable characters"),
1952 bformat(_("The following characters that are used in an index name are not\n"
1953 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1954 indexname_latex.second));
1956 lyxpreamble += "\\newindex[";
1957 lyxpreamble += indexname_latex.first;
1958 lyxpreamble += "]{";
1959 lyxpreamble += escape(iit->shortcut());
1960 lyxpreamble += "}\n";
1965 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1968 // * Hyperref manual: "Make sure it comes last of your loaded
1969 // packages, to give it a fighting chance of not being over-written,
1970 // since its job is to redefine many LaTeX commands."
1971 // * Email from Heiko Oberdiek: "It is usually better to load babel
1972 // before hyperref. Then hyperref has a chance to detect babel.
1973 // * Has to be loaded before the "LyX specific LaTeX commands" to
1974 // avoid errors with algorithm floats.
1975 // use hyperref explicitly if it is required
1976 if (features.isRequired("hyperref")) {
1977 // pass what we have to stream here, since we need
1978 // to access the stream itself in PDFOptions.
1981 OutputParams tmp_params = features.runparams();
1982 pdfoptions().writeLaTeX(tmp_params, os,
1983 features.isProvided("hyperref"));
1984 // set back for the rest
1985 lyxpreamble.clear();
1986 // correctly break URLs with hyperref and dvi output
1987 if (features.runparams().flavor == OutputParams::LATEX
1988 && features.isAvailable("breakurl"))
1989 lyxpreamble += "\\usepackage{breakurl}\n";
1990 } else if (features.isRequired("nameref"))
1991 // hyperref loads this automatically
1992 lyxpreamble += "\\usepackage{nameref}\n";
1994 // bibtopic needs to be loaded after hyperref.
1995 // the dot provides the aux file naming which LyX can detect.
1996 if (features.mustProvide("bibtopic"))
1997 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1999 // Will be surrounded by \makeatletter and \makeatother when not empty
2000 docstring atlyxpreamble;
2002 // Some macros LyX will need
2003 docstring tmppreamble(features.getMacros());
2005 if (!tmppreamble.empty())
2006 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2007 "LyX specific LaTeX commands.\n"
2008 + tmppreamble + '\n';
2010 // the text class specific preamble
2011 tmppreamble = features.getTClassPreamble();
2012 if (!tmppreamble.empty())
2013 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2014 "Textclass specific LaTeX commands.\n"
2015 + tmppreamble + '\n';
2017 // suppress date if selected
2018 // use \@ifundefined because we cannot be sure that every document class
2019 // has a \date command
2021 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
2023 /* the user-defined preamble */
2024 if (!containsOnly(preamble, " \n\t")) {
2026 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2027 "User specified LaTeX commands.\n";
2029 // Check if the user preamble contains uncodable glyphs
2030 docstring const u_preamble = from_utf8(preamble);
2031 odocstringstream user_preamble;
2032 docstring uncodable_glyphs;
2033 Encoding const * const enc = features.runparams().encoding;
2035 for (size_t n = 0; n < u_preamble.size(); ++n) {
2036 char_type c = u_preamble[n];
2037 if (!enc->encodable(c)) {
2038 docstring const glyph(1, c);
2039 LYXERR0("Uncodable character '"
2041 << "' in user preamble!");
2042 uncodable_glyphs += glyph;
2043 if (features.runparams().dryrun) {
2044 user_preamble << "<" << _("LyX Warning: ")
2045 << _("uncodable character") << " '";
2046 user_preamble.put(c);
2047 user_preamble << "'>";
2050 user_preamble.put(c);
2053 user_preamble << u_preamble;
2055 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2056 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2057 frontend::Alert::warning(
2058 _("Uncodable character in user preamble"),
2060 _("The user preamble of your document contains glyphs "
2061 "that are unknown in the current document encoding "
2062 "(namely %1$s).\nThese glyphs are omitted "
2063 " from the output, which may result in "
2064 "incomplete output."
2065 "\n\nPlease select an appropriate "
2066 "document encoding\n"
2067 "(such as utf8) or change the "
2068 "preamble code accordingly."),
2071 atlyxpreamble += user_preamble.str() + '\n';
2074 // footmisc must be loaded after setspace
2075 // Load it here to avoid clashes with footmisc loaded in the user
2076 // preamble. For that reason we also pass the options via
2077 // \PassOptionsToPackage in getPreamble() and not here.
2078 if (features.mustProvide("footmisc"))
2079 atlyxpreamble += "\\usepackage{footmisc}\n";
2081 // subfig loads internally the LaTeX package "caption". As
2082 // caption is a very popular package, users will load it in
2083 // the preamble. Therefore we must load subfig behind the
2084 // user-defined preamble and check if the caption package was
2085 // loaded or not. For the case that caption is loaded before
2086 // subfig, there is the subfig option "caption=false". This
2087 // option also works when a koma-script class is used and
2088 // koma's own caption commands are used instead of caption. We
2089 // use \PassOptionsToPackage here because the user could have
2090 // already loaded subfig in the preamble.
2091 if (features.mustProvide("subfig")) {
2092 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
2093 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2094 "\\usepackage{subfig}\n";
2097 // Itemize bullet settings need to be last in case the user
2098 // defines their own bullets that use a package included
2099 // in the user-defined preamble -- ARRae
2100 // Actually it has to be done much later than that
2101 // since some packages like frenchb make modifications
2102 // at \begin{document} time -- JMarc
2103 docstring bullets_def;
2104 for (int i = 0; i < 4; ++i) {
2105 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2106 if (bullets_def.empty())
2107 bullets_def += "\\AtBeginDocument{\n";
2108 bullets_def += " \\def\\labelitemi";
2110 // `i' is one less than the item to modify
2117 bullets_def += "ii";
2123 bullets_def += '{' +
2124 user_defined_bullet(i).getText()
2129 if (!bullets_def.empty())
2130 atlyxpreamble += bullets_def + "}\n\n";
2132 if (!atlyxpreamble.empty())
2133 lyxpreamble += "\n\\makeatletter\n"
2134 + atlyxpreamble + "\\makeatother\n\n";
2136 // We try to load babel late, in case it interferes with other packages.
2137 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2138 // called after babel, though.
2139 if (use_babel && !features.isRequired("jurabib")
2140 && !features.isRequired("hyperref")
2141 && !features.isRequired("varioref")
2142 && !features.isRequired("vietnamese")
2143 && !features.isRequired("japanese")) {
2145 lyxpreamble += from_utf8(features.getBabelPresettings());
2146 lyxpreamble += from_utf8(babelCall(language_options.str(),
2147 features.needBabelLangOptions())) + '\n';
2148 lyxpreamble += from_utf8(features.getBabelPostsettings());
2150 if (features.isRequired("bicaption"))
2151 lyxpreamble += "\\usepackage{bicaption}\n";
2152 if (!listings_params.empty() || features.mustProvide("listings"))
2153 lyxpreamble += "\\usepackage{listings}\n";
2154 if (!listings_params.empty()) {
2155 lyxpreamble += "\\lstset{";
2156 // do not test validity because listings_params is
2157 // supposed to be valid
2159 InsetListingsParams(listings_params).separatedParams(true);
2160 lyxpreamble += from_utf8(par);
2161 lyxpreamble += "}\n";
2164 // xunicode needs to be loaded at least after amsmath, amssymb,
2165 // esint and the other packages that provide special glyphs
2166 // The package only supports XeTeX currently.
2167 if (features.runparams().flavor == OutputParams::XETEX
2169 lyxpreamble += "\\usepackage{xunicode}\n";
2171 // Polyglossia must be loaded last
2172 if (use_polyglossia) {
2174 lyxpreamble += "\\usepackage{polyglossia}\n";
2175 // set the main language
2176 lyxpreamble += "\\setdefaultlanguage";
2177 if (!language->polyglossiaOpts().empty())
2178 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
2179 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
2180 // now setup the other languages
2181 set<string> const polylangs =
2182 features.getPolyglossiaLanguages();
2183 for (set<string>::const_iterator mit = polylangs.begin();
2184 mit != polylangs.end() ; ++mit) {
2185 // We do not output the options here; they are output in
2186 // the language switch commands. This is safer if multiple
2187 // varieties are used.
2188 if (*mit == language->polyglossia())
2190 lyxpreamble += "\\setotherlanguage";
2191 lyxpreamble += "{" + from_ascii(*mit) + "}\n";
2195 // Load custom language package here
2196 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2197 if (lang_package == "default")
2198 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2200 lyxpreamble += from_utf8(lang_package);
2201 lyxpreamble += '\n';
2204 docstring const i18npreamble =
2205 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2206 if (!i18npreamble.empty())
2207 lyxpreamble += i18npreamble + '\n';
2215 void BufferParams::useClassDefaults()
2217 DocumentClass const & tclass = documentClass();
2219 sides = tclass.sides();
2220 columns = tclass.columns();
2221 pagestyle = tclass.pagestyle();
2222 use_default_options = true;
2223 // Only if class has a ToC hierarchy
2224 if (tclass.hasTocLevels()) {
2225 secnumdepth = tclass.secnumdepth();
2226 tocdepth = tclass.tocdepth();
2231 bool BufferParams::hasClassDefaults() const
2233 DocumentClass const & tclass = documentClass();
2235 return sides == tclass.sides()
2236 && columns == tclass.columns()
2237 && pagestyle == tclass.pagestyle()
2238 && use_default_options
2239 && secnumdepth == tclass.secnumdepth()
2240 && tocdepth == tclass.tocdepth();
2244 DocumentClass const & BufferParams::documentClass() const
2246 return *doc_class_.get();
2250 DocumentClassConstPtr BufferParams::documentClassPtr() const
2256 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2258 // evil, but this function is evil
2259 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2260 invalidateConverterCache();
2264 bool BufferParams::setBaseClass(string const & classname)
2266 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2267 LayoutFileList & bcl = LayoutFileList::get();
2268 if (!bcl.haveClass(classname)) {
2270 bformat(_("The layout file:\n"
2272 "could not be found. A default textclass with default\n"
2273 "layouts will be used. LyX will not be able to produce\n"
2275 from_utf8(classname));
2276 frontend::Alert::error(_("Document class not found"), s);
2277 bcl.addEmptyClass(classname);
2280 bool const success = bcl[classname].load();
2283 bformat(_("Due to some error in it, the layout file:\n"
2285 "could not be loaded. A default textclass with default\n"
2286 "layouts will be used. LyX will not be able to produce\n"
2288 from_utf8(classname));
2289 frontend::Alert::error(_("Could not load class"), s);
2290 bcl.addEmptyClass(classname);
2293 pimpl_->baseClass_ = classname;
2294 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2299 LayoutFile const * BufferParams::baseClass() const
2301 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2302 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2308 LayoutFileIndex const & BufferParams::baseClassID() const
2310 return pimpl_->baseClass_;
2314 void BufferParams::makeDocumentClass(bool const clone)
2319 invalidateConverterCache();
2320 LayoutModuleList mods;
2321 LayoutModuleList::iterator it = layout_modules_.begin();
2322 LayoutModuleList::iterator en = layout_modules_.end();
2323 for (; it != en; ++it)
2324 mods.push_back(*it);
2326 it = cite_engine_.begin();
2327 en = cite_engine_.end();
2328 for (; it != en; ++it)
2329 mods.push_back(*it);
2331 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2333 TextClass::ReturnValues success = TextClass::OK;
2334 if (!forced_local_layout_.empty())
2335 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2336 if (!local_layout_.empty() &&
2337 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2338 success = doc_class_->read(local_layout_, TextClass::MODULE);
2339 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2340 docstring const msg = _("Error reading internal layout information");
2341 frontend::Alert::warning(_("Read Error"), msg);
2346 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2348 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2352 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2354 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2358 std::string BufferParams::getLocalLayout(bool forced) const
2361 return doc_class_->forcedLayouts();
2363 return local_layout_;
2367 void BufferParams::setLocalLayout(string const & layout, bool forced)
2370 forced_local_layout_ = layout;
2372 local_layout_ = layout;
2376 bool BufferParams::addLayoutModule(string const & modName)
2378 LayoutModuleList::const_iterator it = layout_modules_.begin();
2379 LayoutModuleList::const_iterator end = layout_modules_.end();
2380 for (; it != end; ++it)
2383 layout_modules_.push_back(modName);
2388 string BufferParams::bufferFormat() const
2390 string format = documentClass().outputFormat();
2391 if (format == "latex") {
2393 // FIXME: In this context, this means "xetex or luatex"
2394 // with fontspec. We cannot differentiate further here.
2395 // But maybe use a more appropriate string.
2397 if (encoding().package() == Encoding::japanese)
2404 bool BufferParams::isExportable(string const & format, bool need_viewable) const
2406 FormatList const & formats = exportableFormats(need_viewable);
2407 FormatList::const_iterator fit = formats.begin();
2408 FormatList::const_iterator end = formats.end();
2409 for (; fit != end ; ++fit) {
2410 if ((*fit)->name() == format)
2417 FormatList const & BufferParams::exportableFormats(bool only_viewable) const
2419 FormatList & cached = only_viewable ?
2420 pimpl_->viewableFormatList : pimpl_->exportableFormatList;
2421 bool & valid = only_viewable ?
2422 pimpl_->isViewCacheValid : pimpl_->isExportCacheValid;
2426 vector<string> const backs = backends();
2427 set<string> excludes;
2428 if (useNonTeXFonts) {
2429 excludes.insert("latex");
2430 excludes.insert("pdflatex");
2433 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2434 for (vector<string>::const_iterator it = backs.begin() + 1;
2435 it != backs.end(); ++it) {
2436 FormatList r = theConverters().getReachable(*it, only_viewable,
2438 result.insert(result.end(), r.begin(), r.end());
2440 sort(result.begin(), result.end(), Format::formatSorter);
2447 vector<string> BufferParams::backends() const
2450 string const buffmt = bufferFormat();
2452 // FIXME: Don't hardcode format names here, but use a flag
2453 if (buffmt == "latex") {
2454 if (!useNonTeXFonts) {
2455 v.push_back("pdflatex");
2456 v.push_back("latex");
2458 v.push_back("luatex");
2459 v.push_back("dviluatex");
2460 v.push_back("xetex");
2461 } else if (buffmt == "xetex") {
2462 v.push_back("xetex");
2463 v.push_back("luatex");
2464 v.push_back("dviluatex");
2466 v.push_back(buffmt);
2468 v.push_back("xhtml");
2469 v.push_back("text");
2475 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2477 string const dformat = (format.empty() || format == "default") ?
2478 getDefaultOutputFormat() : format;
2479 DefaultFlavorCache::const_iterator it =
2480 default_flavors_.find(dformat);
2482 if (it != default_flavors_.end())
2485 OutputParams::FLAVOR result = OutputParams::LATEX;
2487 // FIXME It'd be better not to hardcode this, but to do
2488 // something with formats.
2489 if (dformat == "xhtml")
2490 result = OutputParams::HTML;
2491 else if (dformat == "text")
2492 result = OutputParams::TEXT;
2493 else if (dformat == "lyx")
2494 result = OutputParams::LYX;
2495 else if (dformat == "pdflatex")
2496 result = OutputParams::PDFLATEX;
2497 else if (dformat == "xetex")
2498 result = OutputParams::XETEX;
2499 else if (dformat == "luatex")
2500 result = OutputParams::LUATEX;
2501 else if (dformat == "dviluatex")
2502 result = OutputParams::DVILUATEX;
2504 // Try to determine flavor of default output format
2505 vector<string> backs = backends();
2506 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2507 // Get shortest path to format
2508 Graph::EdgePath path;
2509 for (vector<string>::const_iterator it = backs.begin();
2510 it != backs.end(); ++it) {
2511 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2512 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2517 result = theConverters().getFlavor(path);
2520 // cache this flavor
2521 default_flavors_[dformat] = result;
2526 string BufferParams::getDefaultOutputFormat() const
2528 if (!default_output_format.empty()
2529 && default_output_format != "default")
2530 return default_output_format;
2532 || encoding().package() == Encoding::japanese) {
2533 FormatList const & formats = exportableFormats(true);
2534 if (formats.empty())
2536 // return the first we find
2537 return formats.front()->name();
2540 return lyxrc.default_otf_view_format;
2541 return lyxrc.default_view_format;
2544 Font const BufferParams::getFont() const
2546 FontInfo f = documentClass().defaultfont();
2547 if (fonts_default_family == "rmdefault")
2548 f.setFamily(ROMAN_FAMILY);
2549 else if (fonts_default_family == "sfdefault")
2550 f.setFamily(SANS_FAMILY);
2551 else if (fonts_default_family == "ttdefault")
2552 f.setFamily(TYPEWRITER_FAMILY);
2553 return Font(f, language);
2557 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2559 return quoteslangtranslator().find(qs);
2563 bool BufferParams::isLatex() const
2565 return documentClass().outputType() == LATEX;
2569 bool BufferParams::isLiterate() const
2571 return documentClass().outputType() == LITERATE;
2575 bool BufferParams::isDocBook() const
2577 return documentClass().outputType() == DOCBOOK;
2581 void BufferParams::readPreamble(Lexer & lex)
2583 if (lex.getString() != "\\begin_preamble")
2584 lyxerr << "Error (BufferParams::readPreamble):"
2585 "consistency check failed." << endl;
2587 preamble = lex.getLongString("\\end_preamble");
2591 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2593 string const expected = forced ? "\\begin_forced_local_layout" :
2594 "\\begin_local_layout";
2595 if (lex.getString() != expected)
2596 lyxerr << "Error (BufferParams::readLocalLayout):"
2597 "consistency check failed." << endl;
2600 forced_local_layout_ =
2601 lex.getLongString("\\end_forced_local_layout");
2603 local_layout_ = lex.getLongString("\\end_local_layout");
2607 bool BufferParams::setLanguage(string const & lang)
2609 Language const *new_language = languages.getLanguage(lang);
2610 if (!new_language) {
2611 // Language lang was not found
2614 language = new_language;
2619 void BufferParams::readLanguage(Lexer & lex)
2621 if (!lex.next()) return;
2623 string const tmptok = lex.getString();
2625 // check if tmptok is part of tex_babel in tex-defs.h
2626 if (!setLanguage(tmptok)) {
2627 // Language tmptok was not found
2628 language = default_language;
2629 lyxerr << "Warning: Setting language `"
2630 << tmptok << "' to `" << language->lang()
2636 void BufferParams::readGraphicsDriver(Lexer & lex)
2641 string const tmptok = lex.getString();
2642 // check if tmptok is part of tex_graphics in tex_defs.h
2645 string const test = tex_graphics[n++];
2647 if (test == tmptok) {
2648 graphics_driver = tmptok;
2653 "Warning: graphics driver `$$Token' not recognized!\n"
2654 " Setting graphics driver to `default'.\n");
2655 graphics_driver = "default";
2662 void BufferParams::readBullets(Lexer & lex)
2667 int const index = lex.getInteger();
2669 int temp_int = lex.getInteger();
2670 user_defined_bullet(index).setFont(temp_int);
2671 temp_bullet(index).setFont(temp_int);
2673 user_defined_bullet(index).setCharacter(temp_int);
2674 temp_bullet(index).setCharacter(temp_int);
2676 user_defined_bullet(index).setSize(temp_int);
2677 temp_bullet(index).setSize(temp_int);
2681 void BufferParams::readBulletsLaTeX(Lexer & lex)
2683 // The bullet class should be able to read this.
2686 int const index = lex.getInteger();
2688 docstring const temp_str = lex.getDocString();
2690 user_defined_bullet(index).setText(temp_str);
2691 temp_bullet(index).setText(temp_str);
2695 void BufferParams::readModules(Lexer & lex)
2697 if (!lex.eatLine()) {
2698 lyxerr << "Error (BufferParams::readModules):"
2699 "Unexpected end of input." << endl;
2703 string mod = lex.getString();
2704 if (mod == "\\end_modules")
2706 addLayoutModule(mod);
2712 void BufferParams::readRemovedModules(Lexer & lex)
2714 if (!lex.eatLine()) {
2715 lyxerr << "Error (BufferParams::readRemovedModules):"
2716 "Unexpected end of input." << endl;
2720 string mod = lex.getString();
2721 if (mod == "\\end_removed_modules")
2723 removed_modules_.push_back(mod);
2726 // now we want to remove any removed modules that were previously
2727 // added. normally, that will be because default modules were added in
2728 // setBaseClass(), which gets called when \textclass is read at the
2729 // start of the read.
2730 list<string>::const_iterator rit = removed_modules_.begin();
2731 list<string>::const_iterator const ren = removed_modules_.end();
2732 for (; rit != ren; ++rit) {
2733 LayoutModuleList::iterator const mit = layout_modules_.begin();
2734 LayoutModuleList::iterator const men = layout_modules_.end();
2735 LayoutModuleList::iterator found = find(mit, men, *rit);
2738 layout_modules_.erase(found);
2743 void BufferParams::readIncludeonly(Lexer & lex)
2745 if (!lex.eatLine()) {
2746 lyxerr << "Error (BufferParams::readIncludeonly):"
2747 "Unexpected end of input." << endl;
2751 string child = lex.getString();
2752 if (child == "\\end_includeonly")
2754 included_children_.push_back(child);
2760 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2762 switch (papersize) {
2764 // could be anything, so don't guess
2766 case PAPER_CUSTOM: {
2767 if (purpose == XDVI && !paperwidth.empty() &&
2768 !paperheight.empty()) {
2769 // heightxwidth<unit>
2770 string first = paperwidth;
2771 string second = paperheight;
2772 if (orientation == ORIENTATION_LANDSCAPE)
2775 return first.erase(first.length() - 2)
2781 // dvips and dvipdfm do not know this
2782 if (purpose == DVIPS || purpose == DVIPDFM)
2786 if (purpose == DVIPS || purpose == DVIPDFM)
2790 if (purpose == DVIPS || purpose == DVIPDFM)
2800 if (purpose == DVIPS || purpose == DVIPDFM)
2804 if (purpose == DVIPS || purpose == DVIPDFM)
2808 if (purpose == DVIPS || purpose == DVIPDFM)
2812 if (purpose == DVIPS || purpose == DVIPDFM)
2816 if (purpose == DVIPS || purpose == DVIPDFM)
2820 // dvipdfm does not know this
2821 if (purpose == DVIPDFM)
2825 if (purpose == DVIPDFM)
2829 if (purpose == DVIPS || purpose == DVIPDFM)
2833 if (purpose == DVIPS || purpose == DVIPDFM)
2837 if (purpose == DVIPS || purpose == DVIPDFM)
2841 if (purpose == DVIPS || purpose == DVIPDFM)
2845 if (purpose == DVIPS || purpose == DVIPDFM)
2849 if (purpose == DVIPS || purpose == DVIPDFM)
2853 if (purpose == DVIPS || purpose == DVIPDFM)
2857 if (purpose == DVIPS || purpose == DVIPDFM)
2861 if (purpose == DVIPS || purpose == DVIPDFM)
2865 if (purpose == DVIPS || purpose == DVIPDFM)
2869 if (purpose == DVIPS || purpose == DVIPDFM)
2873 if (purpose == DVIPS || purpose == DVIPDFM)
2877 if (purpose == DVIPS || purpose == DVIPDFM)
2881 if (purpose == DVIPS || purpose == DVIPDFM)
2885 if (purpose == DVIPS || purpose == DVIPDFM)
2888 case PAPER_USEXECUTIVE:
2889 // dvipdfm does not know this
2890 if (purpose == DVIPDFM)
2895 case PAPER_USLETTER:
2897 if (purpose == XDVI)
2904 string const BufferParams::dvips_options() const
2908 // If the class loads the geometry package, we do not know which
2909 // paper size is used, since we do not set it (bug 7013).
2910 // Therefore we must not specify any argument here.
2911 // dvips gets the correct paper size via DVI specials in this case
2912 // (if the class uses the geometry package correctly).
2913 if (documentClass().provides("geometry"))
2917 && papersize == PAPER_CUSTOM
2918 && !lyxrc.print_paper_dimension_flag.empty()
2919 && !paperwidth.empty()
2920 && !paperheight.empty()) {
2921 // using a custom papersize
2922 result = lyxrc.print_paper_dimension_flag;
2923 result += ' ' + paperwidth;
2924 result += ',' + paperheight;
2926 string const paper_option = paperSizeName(DVIPS);
2927 if (!paper_option.empty() && (paper_option != "letter" ||
2928 orientation != ORIENTATION_LANDSCAPE)) {
2929 // dvips won't accept -t letter -t landscape.
2930 // In all other cases, include the paper size
2932 result = lyxrc.print_paper_flag;
2933 result += ' ' + paper_option;
2936 if (orientation == ORIENTATION_LANDSCAPE &&
2937 papersize != PAPER_CUSTOM)
2938 result += ' ' + lyxrc.print_landscape_flag;
2943 string const BufferParams::font_encoding() const
2945 return font_encodings().empty() ? "default" : font_encodings().back();
2949 vector<string> const BufferParams::font_encodings() const
2951 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2953 vector<string> fontencs;
2955 // "default" means "no explicit font encoding"
2956 if (doc_fontenc != "default") {
2957 fontencs = getVectorFromString(doc_fontenc);
2958 if (!language->fontenc().empty()
2959 && ascii_lowercase(language->fontenc()) != "none") {
2960 vector<string> fencs = getVectorFromString(language->fontenc());
2961 vector<string>::const_iterator fit = fencs.begin();
2962 for (; fit != fencs.end(); ++fit) {
2963 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2964 fontencs.push_back(*fit);
2973 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2975 // suppress the babel call if there is no BabelName defined
2976 // for the document language in the lib/languages file and if no
2977 // other languages are used (lang_opts is then empty)
2978 if (lang_opts.empty())
2980 // either a specific language (AsBabelOptions setting in
2981 // lib/languages) or the prefs require the languages to
2982 // be submitted to babel itself (not the class).
2984 return "\\usepackage[" + lang_opts + "]{babel}";
2985 return "\\usepackage{babel}";
2989 docstring BufferParams::getGraphicsDriver(string const & package) const
2993 if (package == "geometry") {
2994 if (graphics_driver == "dvips"
2995 || graphics_driver == "dvipdfm"
2996 || graphics_driver == "pdftex"
2997 || graphics_driver == "vtex")
2998 result = from_ascii(graphics_driver);
2999 else if (graphics_driver == "dvipdfmx")
3000 result = from_ascii("dvipdfm");
3007 void BufferParams::writeEncodingPreamble(otexstream & os,
3008 LaTeXFeatures & features) const
3010 // XeTeX/LuaTeX: (see also #9740)
3011 // With Unicode fonts we use utf8-plain without encoding package.
3012 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
3013 // XeTeX must use ASCII encoding (see Buffer.cpp),
3014 // for LuaTeX, we load "luainputenc" (see below).
3015 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
3018 if (inputenc == "auto") {
3019 string const doc_encoding =
3020 language->encoding()->latexName();
3021 Encoding::Package const package =
3022 language->encoding()->package();
3024 // Create list of inputenc options:
3025 set<string> encodings;
3026 // luainputenc fails with more than one encoding
3027 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
3028 // list all input encodings used in the document
3029 encodings = features.getEncodingSet(doc_encoding);
3031 // If the "japanese" package (i.e. pLaTeX) is used,
3032 // inputenc must be omitted.
3033 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
3034 if ((!encodings.empty() || package == Encoding::inputenc)
3035 && !features.isRequired("japanese")
3036 && !features.isProvided("inputenc")) {
3037 os << "\\usepackage[";
3038 set<string>::const_iterator it = encodings.begin();
3039 set<string>::const_iterator const end = encodings.end();
3041 os << from_ascii(*it);
3044 for (; it != end; ++it)
3045 os << ',' << from_ascii(*it);
3046 if (package == Encoding::inputenc) {
3047 if (!encodings.empty())
3049 os << from_ascii(doc_encoding);
3051 if (features.runparams().flavor == OutputParams::LUATEX
3052 || features.runparams().flavor == OutputParams::DVILUATEX)
3053 os << "]{luainputenc}\n";
3055 os << "]{inputenc}\n";
3057 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3058 if (language->encoding()->name() == "utf8-cjk"
3059 && LaTeXFeatures::isAvailable("CJKutf8"))
3060 os << "\\usepackage{CJKutf8}\n";
3062 os << "\\usepackage{CJK}\n";
3064 } else if (inputenc != "default") {
3065 switch (encoding().package()) {
3066 case Encoding::none:
3067 case Encoding::japanese:
3069 case Encoding::inputenc:
3070 // do not load inputenc if japanese is used
3071 // or if the class provides inputenc
3072 if (features.isRequired("japanese")
3073 || features.isProvided("inputenc"))
3075 os << "\\usepackage[" << from_ascii(encoding().latexName());
3076 if (features.runparams().flavor == OutputParams::LUATEX
3077 || features.runparams().flavor == OutputParams::DVILUATEX)
3078 os << "]{luainputenc}\n";
3080 os << "]{inputenc}\n";
3083 if (encoding().name() == "utf8-cjk"
3084 && LaTeXFeatures::isAvailable("CJKutf8"))
3085 os << "\\usepackage{CJKutf8}\n";
3087 os << "\\usepackage{CJK}\n";
3090 // Load the CJK package if needed by a secondary language.
3091 // If the main encoding is some variant of UTF8, use CJKutf8.
3092 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3093 if (encoding().iconvName() == "UTF-8"
3094 && LaTeXFeatures::isAvailable("CJKutf8"))
3095 os << "\\usepackage{CJKutf8}\n";
3097 os << "\\usepackage{CJK}\n";
3103 string const BufferParams::parseFontName(string const & name) const
3105 string mangled = name;
3106 size_t const idx = mangled.find('[');
3107 if (idx == string::npos || idx == 0)
3110 return mangled.substr(0, idx - 1);
3114 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3116 if (fontsRoman() == "default" && fontsSans() == "default"
3117 && fontsTypewriter() == "default"
3118 && (fontsMath() == "default" || fontsMath() == "auto"))
3124 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3125 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3126 * Mapping=tex-text option assures TeX ligatures (such as "--")
3127 * are resolved. Note that tt does not use these ligatures.
3129 * -- add more GUI options?
3130 * -- add more fonts (fonts for other scripts)
3131 * -- if there's a way to find out if a font really supports
3132 * OldStyle, enable/disable the widget accordingly.
3134 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3135 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3136 // However, until v.2 (2010/07/11) fontspec only knew
3137 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3138 // was introduced for both XeTeX and LuaTeX (LuaTeX
3139 // didn't understand "Mapping=tex-text", while XeTeX
3140 // understood both. With most recent versions, both
3141 // variants are understood by both engines. However,
3142 // we want to provide support for at least TeXLive 2009
3143 // (for XeTeX; LuaTeX is only supported as of v.2)
3144 string const texmapping =
3145 (features.runparams().flavor == OutputParams::XETEX) ?
3146 "Mapping=tex-text" : "Ligatures=TeX";
3147 if (fontsRoman() != "default") {
3148 os << "\\setmainfont[" << texmapping;
3149 if (fonts_old_figures)
3150 os << ",Numbers=OldStyle";
3151 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3153 if (fontsSans() != "default") {
3154 string const sans = parseFontName(fontsSans());
3155 if (fontsSansScale() != 100)
3156 os << "\\setsansfont[Scale="
3157 << float(fontsSansScale()) / 100
3158 << "," << texmapping << "]{"
3161 os << "\\setsansfont[" << texmapping << "]{"
3164 if (fontsTypewriter() != "default") {
3165 string const mono = parseFontName(fontsTypewriter());
3166 if (fontsTypewriterScale() != 100)
3167 os << "\\setmonofont[Scale="
3168 << float(fontsTypewriterScale()) / 100
3172 os << "\\setmonofont{"
3179 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3180 bool const dryrun = features.runparams().dryrun;
3181 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3182 bool const nomath = (fontsMath() == "default");
3185 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3186 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3190 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3191 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3192 nomath, fontsSansScale());
3194 // MONOSPACED/TYPEWRITER
3195 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3196 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3197 nomath, fontsTypewriterScale());
3200 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3201 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3208 Encoding const & BufferParams::encoding() const
3210 // Main encoding for LaTeX output.
3212 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3213 // As the "flavor" is only known once export started, this
3214 // cannot be handled here. Instead, runparams.encoding is set
3215 // to ASCII in Buffer::makeLaTeXFile (for export)
3216 // and Buffer::writeLaTeXSource (for preview).
3218 return *(encodings.fromLyXName("utf8-plain"));
3219 if (inputenc == "auto" || inputenc == "default")
3220 return *language->encoding();
3221 Encoding const * const enc = encodings.fromLyXName(inputenc);
3224 LYXERR0("Unknown inputenc value `" << inputenc
3225 << "'. Using `auto' instead.");
3226 return *language->encoding();
3230 bool BufferParams::addCiteEngine(string const & engine)
3232 LayoutModuleList::const_iterator it = cite_engine_.begin();
3233 LayoutModuleList::const_iterator en = cite_engine_.end();
3234 for (; it != en; ++it)
3237 cite_engine_.push_back(engine);
3242 bool BufferParams::addCiteEngine(vector<string> const & engine)
3244 vector<string>::const_iterator it = engine.begin();
3245 vector<string>::const_iterator en = engine.end();
3247 for (; it != en; ++it)
3248 if (!addCiteEngine(*it))
3254 string const & BufferParams::defaultBiblioStyle() const
3256 return documentClass().defaultBiblioStyle();
3260 bool const & BufferParams::fullAuthorList() const
3262 return documentClass().fullAuthorList();
3266 void BufferParams::setCiteEngine(string const & engine)
3269 addCiteEngine(engine);
3273 void BufferParams::setCiteEngine(vector<string> const & engine)
3276 addCiteEngine(engine);
3280 vector<string> BufferParams::citeCommands() const
3282 static CitationStyle const default_style;
3283 vector<string> commands =
3284 documentClass().citeCommands(citeEngineType());
3285 if (commands.empty())
3286 commands.push_back(default_style.cmd);
3291 vector<CitationStyle> BufferParams::citeStyles() const
3293 static CitationStyle const default_style;
3294 vector<CitationStyle> styles =
3295 documentClass().citeStyles(citeEngineType());
3297 styles.push_back(default_style);
3301 void BufferParams::invalidateConverterCache() const
3303 pimpl_->isExportCacheValid = false;
3304 pimpl_->isViewCacheValid = false;