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", ""
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);
154 QuotesStyleTranslator const & quotesstyletranslator()
156 static QuotesStyleTranslator const translator =
157 init_quotesstyletranslator();
163 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
166 static PaperSizeTranslator initPaperSizeTranslator()
168 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
169 translator.addPair(string_papersize[1], PAPER_CUSTOM);
170 translator.addPair(string_papersize[2], PAPER_USLETTER);
171 translator.addPair(string_papersize[3], PAPER_USLEGAL);
172 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
173 translator.addPair(string_papersize[5], PAPER_A0);
174 translator.addPair(string_papersize[6], PAPER_A1);
175 translator.addPair(string_papersize[7], PAPER_A2);
176 translator.addPair(string_papersize[8], PAPER_A3);
177 translator.addPair(string_papersize[9], PAPER_A4);
178 translator.addPair(string_papersize[10], PAPER_A5);
179 translator.addPair(string_papersize[11], PAPER_A6);
180 translator.addPair(string_papersize[12], PAPER_B0);
181 translator.addPair(string_papersize[13], PAPER_B1);
182 translator.addPair(string_papersize[14], PAPER_B2);
183 translator.addPair(string_papersize[15], PAPER_B3);
184 translator.addPair(string_papersize[16], PAPER_B4);
185 translator.addPair(string_papersize[17], PAPER_B5);
186 translator.addPair(string_papersize[18], PAPER_B6);
187 translator.addPair(string_papersize[19], PAPER_C0);
188 translator.addPair(string_papersize[20], PAPER_C1);
189 translator.addPair(string_papersize[21], PAPER_C2);
190 translator.addPair(string_papersize[22], PAPER_C3);
191 translator.addPair(string_papersize[23], PAPER_C4);
192 translator.addPair(string_papersize[24], PAPER_C5);
193 translator.addPair(string_papersize[25], PAPER_C6);
194 translator.addPair(string_papersize[26], PAPER_JISB0);
195 translator.addPair(string_papersize[27], PAPER_JISB1);
196 translator.addPair(string_papersize[28], PAPER_JISB2);
197 translator.addPair(string_papersize[29], PAPER_JISB3);
198 translator.addPair(string_papersize[30], PAPER_JISB4);
199 translator.addPair(string_papersize[31], PAPER_JISB5);
200 translator.addPair(string_papersize[32], PAPER_JISB6);
205 PaperSizeTranslator const & papersizetranslator()
207 static PaperSizeTranslator const translator =
208 initPaperSizeTranslator();
214 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
217 PaperOrientationTranslator const init_paperorientationtranslator()
219 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
220 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
225 PaperOrientationTranslator const & paperorientationtranslator()
227 static PaperOrientationTranslator const translator =
228 init_paperorientationtranslator();
234 typedef Translator<int, PageSides> SidesTranslator;
237 SidesTranslator const init_sidestranslator()
239 SidesTranslator translator(1, OneSide);
240 translator.addPair(2, TwoSides);
245 SidesTranslator const & sidestranslator()
247 static SidesTranslator const translator = init_sidestranslator();
253 typedef Translator<int, BufferParams::Package> PackageTranslator;
256 PackageTranslator const init_packagetranslator()
258 PackageTranslator translator(0, BufferParams::package_off);
259 translator.addPair(1, BufferParams::package_auto);
260 translator.addPair(2, BufferParams::package_on);
265 PackageTranslator const & packagetranslator()
267 static PackageTranslator const translator =
268 init_packagetranslator();
274 typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
277 CiteEngineTypeTranslator const init_citeenginetypetranslator()
279 CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
280 translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
281 translator.addPair("default", ENGINE_TYPE_DEFAULT);
286 CiteEngineTypeTranslator const & citeenginetypetranslator()
288 static CiteEngineTypeTranslator const translator =
289 init_citeenginetypetranslator();
295 typedef Translator<string, Spacing::Space> SpaceTranslator;
298 SpaceTranslator const init_spacetranslator()
300 SpaceTranslator translator("default", Spacing::Default);
301 translator.addPair("single", Spacing::Single);
302 translator.addPair("onehalf", Spacing::Onehalf);
303 translator.addPair("double", Spacing::Double);
304 translator.addPair("other", Spacing::Other);
309 SpaceTranslator const & spacetranslator()
311 static SpaceTranslator const translator = init_spacetranslator();
316 bool inSystemDir(FileName const & document_dir, string & system_dir)
318 // A document is assumed to be in a system LyX directory (not
319 // necessarily the system directory of the running instance)
320 // if both "configure.py" and "chkconfig.ltx" are found in
321 // either document_dir/../ or document_dir/../../.
322 // If true, the system directory path is returned in system_dir
323 // with a trailing path separator.
325 string const msg = "Checking whether document is in a system dir...";
327 string dir = document_dir.absFileName();
329 for (int i = 0; i < 2; ++i) {
330 dir = addPath(dir, "..");
331 if (!fileSearch(dir, "configure.py").empty() &&
332 !fileSearch(dir, "chkconfig.ltx").empty()) {
333 LYXERR(Debug::FILES, msg << " yes");
334 system_dir = addPath(FileName(dir).realPath(), "");
339 LYXERR(Debug::FILES, msg << " no");
340 system_dir = string();
347 class BufferParams::Impl
352 AuthorList authorlist;
353 BranchList branchlist;
354 Bullet temp_bullets[4];
355 Bullet user_defined_bullets[4];
356 IndicesList indiceslist;
358 /** This is the amount of space used for paragraph_separation "skip",
359 * and for detached paragraphs in "indented" documents.
363 PDFOptions pdfoptions;
364 LayoutFileIndex baseClass_;
365 FormatList exportableFormatList;
366 FormatList viewableFormatList;
367 bool isViewCacheValid;
368 bool isExportCacheValid;
372 BufferParams::Impl::Impl()
373 : defskip(VSpace::MEDSKIP), baseClass_(string("")),
374 isViewCacheValid(false), isExportCacheValid(false)
376 // set initial author
378 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
383 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
386 return new BufferParams::Impl(*ptr);
390 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
396 BufferParams::BufferParams()
399 setBaseClass(defaultBaseclass());
400 cite_engine_.push_back("basic");
401 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
403 paragraph_separation = ParagraphIndentSeparation;
404 quotes_style = InsetQuotesParams::EnglishQuotes;
405 fontsize = "default";
408 papersize = PAPER_DEFAULT;
409 orientation = ORIENTATION_PORTRAIT;
410 use_geometry = false;
411 biblio_style = "plain";
412 use_bibtopic = false;
414 save_transient_properties = true;
415 track_changes = false;
416 output_changes = false;
417 use_default_options = true;
418 maintain_unincluded_children = false;
421 language = default_language;
423 fonts_roman[0] = "default";
424 fonts_roman[1] = "default";
425 fonts_sans[0] = "default";
426 fonts_sans[1] = "default";
427 fonts_typewriter[0] = "default";
428 fonts_typewriter[1] = "default";
429 fonts_math[0] = "auto";
430 fonts_math[1] = "auto";
431 fonts_default_family = "default";
432 useNonTeXFonts = false;
433 use_microtype = false;
434 fonts_expert_sc = false;
435 fonts_old_figures = false;
436 fonts_sans_scale[0] = 100;
437 fonts_sans_scale[1] = 100;
438 fonts_typewriter_scale[0] = 100;
439 fonts_typewriter_scale[1] = 100;
441 lang_package = "default";
442 graphics_driver = "default";
443 default_output_format = "default";
444 bibtex_command = "default";
445 index_command = "default";
448 listings_params = string();
449 pagestyle = "default";
450 suppress_date = false;
451 justification = true;
452 // no color is the default (white)
453 backgroundcolor = lyx::rgbFromHexName("#ffffff");
454 isbackgroundcolor = false;
455 // no color is the default (black)
456 fontcolor = lyx::rgbFromHexName("#000000");
458 // light gray is the default font color for greyed-out notes
459 notefontcolor = lyx::rgbFromHexName("#cccccc");
460 boxbgcolor = lyx::rgbFromHexName("#ff0000");
461 compressed = lyxrc.save_compressed;
462 for (int iter = 0; iter < 4; ++iter) {
463 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
464 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
467 indiceslist().addDefault(B_("Index"));
468 html_be_strict = false;
469 html_math_output = MathML;
470 html_math_img_scale = 1.0;
471 html_css_as_file = false;
472 display_pixel_ratio = 1.0;
477 // map current author
478 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
482 docstring BufferParams::B_(string const & l10n) const
484 LASSERT(language, return from_utf8(l10n));
485 return getMessages(language->code()).get(l10n);
489 BufferParams::Package BufferParams::use_package(std::string const & p) const
491 PackageMap::const_iterator it = use_packages.find(p);
492 if (it == use_packages.end())
498 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
504 map<string, string> const & BufferParams::auto_packages()
506 static map<string, string> packages;
507 if (packages.empty()) {
508 // We could have a race condition here that two threads
509 // discover an empty map at the same time and want to fill
510 // it, but that is no problem, since the same contents is
511 // filled in twice then. Having the locker inside the
512 // packages.empty() condition has the advantage that we
513 // don't need the mutex overhead for simple reading.
515 Mutex::Locker locker(&mutex);
516 // adding a package here implies a file format change!
517 packages["amsmath"] =
518 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
519 packages["amssymb"] =
520 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
522 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
524 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
525 packages["mathdots"] =
526 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
527 packages["mathtools"] =
528 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
530 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
531 packages["stackrel"] =
532 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
533 packages["stmaryrd"] =
534 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");
535 packages["undertilde"] =
536 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
542 AuthorList & BufferParams::authors()
544 return pimpl_->authorlist;
548 AuthorList const & BufferParams::authors() const
550 return pimpl_->authorlist;
554 void BufferParams::addAuthor(Author a)
556 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
560 BranchList & BufferParams::branchlist()
562 return pimpl_->branchlist;
566 BranchList const & BufferParams::branchlist() const
568 return pimpl_->branchlist;
572 IndicesList & BufferParams::indiceslist()
574 return pimpl_->indiceslist;
578 IndicesList const & BufferParams::indiceslist() const
580 return pimpl_->indiceslist;
584 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
586 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
587 return pimpl_->temp_bullets[index];
591 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
593 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
594 return pimpl_->temp_bullets[index];
598 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
600 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
601 return pimpl_->user_defined_bullets[index];
605 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
607 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
608 return pimpl_->user_defined_bullets[index];
612 Spacing & BufferParams::spacing()
614 return pimpl_->spacing;
618 Spacing const & BufferParams::spacing() const
620 return pimpl_->spacing;
624 PDFOptions & BufferParams::pdfoptions()
626 return pimpl_->pdfoptions;
630 PDFOptions const & BufferParams::pdfoptions() const
632 return pimpl_->pdfoptions;
636 HSpace const & BufferParams::getIndentation() const
638 return pimpl_->indentation;
642 void BufferParams::setIndentation(HSpace const & indent)
644 pimpl_->indentation = indent;
648 VSpace const & BufferParams::getDefSkip() const
650 return pimpl_->defskip;
654 void BufferParams::setDefSkip(VSpace const & vs)
656 // DEFSKIP will cause an infinite loop
657 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
658 pimpl_->defskip = vs;
662 string BufferParams::readToken(Lexer & lex, string const & token,
663 FileName const & filepath)
667 if (token == "\\textclass") {
669 string const classname = lex.getString();
670 // if there exists a local layout file, ignore the system one
671 // NOTE: in this case, the textclass (.cls file) is assumed to
674 LayoutFileList & bcl = LayoutFileList::get();
675 if (!filepath.empty()) {
676 // If classname is an absolute path, the document is
677 // using a local layout file which could not be accessed
678 // by a relative path. In this case the path is correct
679 // even if the document was moved to a different
680 // location. However, we will have a problem if the
681 // document was generated on a different platform.
682 bool isabsolute = FileName::isAbsolute(classname);
683 string const classpath = onlyPath(classname);
684 string const path = isabsolute ? classpath
685 : FileName(addPath(filepath.absFileName(),
686 classpath)).realPath();
687 string const oldpath = isabsolute ? string()
688 : FileName(addPath(origin, classpath)).realPath();
689 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
691 // that returns non-empty if a "local" layout file is found.
693 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
694 from_utf8(filepath.absFileName())));
697 setBaseClass(onlyFileName(tcp));
699 setBaseClass(onlyFileName(classname));
700 // We assume that a tex class exists for local or unknown
701 // layouts so this warning, will only be given for system layouts.
702 if (!baseClass()->isTeXClassAvailable()) {
703 docstring const desc =
704 translateIfPossible(from_utf8(baseClass()->description()));
705 docstring const prereqs =
706 from_utf8(baseClass()->prerequisites());
707 docstring const msg =
708 bformat(_("The selected document class\n"
710 "requires external files that are not available.\n"
711 "The document class can still be used, but the\n"
712 "document cannot be compiled until the following\n"
713 "prerequisites are installed:\n"
715 "See section 3.1.2.2 (Class Availability) of the\n"
716 "User's Guide for more information."), desc, prereqs);
717 frontend::Alert::warning(_("Document class not available"),
720 } else if (token == "\\save_transient_properties") {
721 lex >> save_transient_properties;
722 } else if (token == "\\origin") {
724 origin = lex.getString();
725 string const sysdirprefix = "/systemlyxdir/";
726 if (prefixIs(origin, sysdirprefix)) {
728 if (inSystemDir(filepath, docsys))
729 origin.replace(0, sysdirprefix.length() - 1, docsys);
731 origin.replace(0, sysdirprefix.length() - 1,
732 package().system_support().absFileName());
734 } else if (token == "\\begin_preamble") {
736 } else if (token == "\\begin_local_layout") {
737 readLocalLayout(lex, false);
738 } else if (token == "\\begin_forced_local_layout") {
739 readLocalLayout(lex, true);
740 } else if (token == "\\begin_modules") {
742 } else if (token == "\\begin_removed_modules") {
743 readRemovedModules(lex);
744 } else if (token == "\\begin_includeonly") {
745 readIncludeonly(lex);
746 } else if (token == "\\maintain_unincluded_children") {
747 lex >> maintain_unincluded_children;
748 } else if (token == "\\options") {
750 options = lex.getString();
751 } else if (token == "\\use_default_options") {
752 lex >> use_default_options;
753 } else if (token == "\\master") {
755 master = lex.getString();
756 if (!filepath.empty() && FileName::isAbsolute(origin)) {
757 bool const isabs = FileName::isAbsolute(master);
758 FileName const abspath(isabs ? master : origin + master);
759 bool const moved = filepath != FileName(origin);
760 if (moved && abspath.exists()) {
761 docstring const path = isabs
763 : from_utf8(abspath.realPath());
764 docstring const refpath =
765 from_utf8(filepath.absFileName());
766 master = to_utf8(makeRelPath(path, refpath));
769 } else if (token == "\\suppress_date") {
770 lex >> suppress_date;
771 } else if (token == "\\justification") {
772 lex >> justification;
773 } else if (token == "\\language") {
775 } else if (token == "\\language_package") {
777 lang_package = lex.getString();
778 } else if (token == "\\inputencoding") {
780 } else if (token == "\\graphics") {
781 readGraphicsDriver(lex);
782 } else if (token == "\\default_output_format") {
783 lex >> default_output_format;
784 } else if (token == "\\bibtex_command") {
786 bibtex_command = lex.getString();
787 } else if (token == "\\index_command") {
789 index_command = lex.getString();
790 } else if (token == "\\fontencoding") {
792 fontenc = lex.getString();
793 } else if (token == "\\font_roman") {
794 lex >> fonts_roman[0];
795 lex >> fonts_roman[1];
796 } else if (token == "\\font_sans") {
797 lex >> fonts_sans[0];
798 lex >> fonts_sans[1];
799 } else if (token == "\\font_typewriter") {
800 lex >> fonts_typewriter[0];
801 lex >> fonts_typewriter[1];
802 } else if (token == "\\font_math") {
803 lex >> fonts_math[0];
804 lex >> fonts_math[1];
805 } else if (token == "\\font_default_family") {
806 lex >> fonts_default_family;
807 } else if (token == "\\use_non_tex_fonts") {
808 lex >> useNonTeXFonts;
809 } else if (token == "\\font_sc") {
810 lex >> fonts_expert_sc;
811 } else if (token == "\\font_osf") {
812 lex >> fonts_old_figures;
813 } else if (token == "\\font_sf_scale") {
814 lex >> fonts_sans_scale[0];
815 lex >> fonts_sans_scale[1];
816 } else if (token == "\\font_tt_scale") {
817 lex >> fonts_typewriter_scale[0];
818 lex >> fonts_typewriter_scale[1];
819 } else if (token == "\\font_cjk") {
821 } else if (token == "\\use_microtype") {
822 lex >> use_microtype;
823 } else if (token == "\\paragraph_separation") {
826 paragraph_separation = parseptranslator().find(parsep);
827 } else if (token == "\\paragraph_indentation") {
829 string indentation = lex.getString();
830 pimpl_->indentation = HSpace(indentation);
831 } else if (token == "\\defskip") {
833 string const defskip = lex.getString();
834 pimpl_->defskip = VSpace(defskip);
835 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
837 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
838 } else if (token == "\\quotes_style") {
841 quotes_style = quotesstyletranslator().find(qstyle);
842 } else if (token == "\\papersize") {
845 papersize = papersizetranslator().find(ppsize);
846 } else if (token == "\\use_geometry") {
848 } else if (token == "\\use_package") {
853 use_package(package, packagetranslator().find(use));
854 } else if (token == "\\cite_engine") {
856 vector<string> engine = getVectorFromString(lex.getString());
857 setCiteEngine(engine);
858 } else if (token == "\\cite_engine_type") {
861 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
862 } else if (token == "\\biblio_style") {
864 biblio_style = lex.getString();
865 } else if (token == "\\use_bibtopic") {
867 } else if (token == "\\use_indices") {
869 } else if (token == "\\tracking_changes") {
870 lex >> track_changes;
871 } else if (token == "\\output_changes") {
872 lex >> output_changes;
873 } else if (token == "\\branch") {
875 docstring branch = lex.getDocString();
876 branchlist().add(branch);
879 string const tok = lex.getString();
880 if (tok == "\\end_branch")
882 Branch * branch_ptr = branchlist().find(branch);
883 if (tok == "\\selected") {
886 branch_ptr->setSelected(lex.getInteger());
888 if (tok == "\\filename_suffix") {
891 branch_ptr->setFileNameSuffix(lex.getInteger());
893 if (tok == "\\color") {
895 string color = lex.getString();
897 branch_ptr->setColor(color);
898 // Update also the Color table:
900 color = lcolor.getX11Name(Color_background);
902 lcolor.setColor(to_utf8(branch), color);
905 } else if (token == "\\index") {
907 docstring index = lex.getDocString();
909 indiceslist().add(index);
912 string const tok = lex.getString();
913 if (tok == "\\end_index")
915 Index * index_ptr = indiceslist().find(index);
916 if (tok == "\\shortcut") {
918 shortcut = lex.getDocString();
920 index_ptr->setShortcut(shortcut);
922 if (tok == "\\color") {
924 string color = lex.getString();
926 index_ptr->setColor(color);
927 // Update also the Color table:
929 color = lcolor.getX11Name(Color_background);
931 if (!shortcut.empty())
932 lcolor.setColor(to_utf8(shortcut), color);
935 } else if (token == "\\author") {
937 istringstream ss(lex.getString());
941 } else if (token == "\\paperorientation") {
944 orientation = paperorientationtranslator().find(orient);
945 } else if (token == "\\backgroundcolor") {
947 backgroundcolor = lyx::rgbFromHexName(lex.getString());
948 isbackgroundcolor = true;
949 } else if (token == "\\fontcolor") {
951 fontcolor = lyx::rgbFromHexName(lex.getString());
953 } else if (token == "\\notefontcolor") {
955 string color = lex.getString();
956 notefontcolor = lyx::rgbFromHexName(color);
957 lcolor.setColor("notefontcolor", color);
958 } else if (token == "\\boxbgcolor") {
960 string color = lex.getString();
961 boxbgcolor = lyx::rgbFromHexName(color);
962 lcolor.setColor("boxbgcolor", color);
963 } else if (token == "\\paperwidth") {
965 } else if (token == "\\paperheight") {
967 } else if (token == "\\leftmargin") {
969 } else if (token == "\\topmargin") {
971 } else if (token == "\\rightmargin") {
973 } else if (token == "\\bottommargin") {
975 } else if (token == "\\headheight") {
977 } else if (token == "\\headsep") {
979 } else if (token == "\\footskip") {
981 } else if (token == "\\columnsep") {
983 } else if (token == "\\paperfontsize") {
985 } else if (token == "\\papercolumns") {
987 } else if (token == "\\listings_params") {
990 listings_params = InsetListingsParams(par).params();
991 } else if (token == "\\papersides") {
994 sides = sidestranslator().find(psides);
995 } else if (token == "\\paperpagestyle") {
997 } else if (token == "\\bullet") {
999 } else if (token == "\\bulletLaTeX") {
1000 readBulletsLaTeX(lex);
1001 } else if (token == "\\secnumdepth") {
1003 } else if (token == "\\tocdepth") {
1005 } else if (token == "\\spacing") {
1009 if (nspacing == "other") {
1012 spacing().set(spacetranslator().find(nspacing), tmp_val);
1013 } else if (token == "\\float_placement") {
1014 lex >> float_placement;
1016 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
1017 string toktmp = pdfoptions().readToken(lex, token);
1018 if (!toktmp.empty()) {
1019 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
1023 } else if (token == "\\html_math_output") {
1026 html_math_output = static_cast<MathOutput>(temp);
1027 } else if (token == "\\html_be_strict") {
1028 lex >> html_be_strict;
1029 } else if (token == "\\html_css_as_file") {
1030 lex >> html_css_as_file;
1031 } else if (token == "\\html_math_img_scale") {
1032 lex >> html_math_img_scale;
1033 } else if (token == "\\html_latex_start") {
1035 html_latex_start = lex.getString();
1036 } else if (token == "\\html_latex_end") {
1038 html_latex_end = lex.getString();
1039 } else if (token == "\\output_sync") {
1041 } else if (token == "\\output_sync_macro") {
1042 lex >> output_sync_macro;
1043 } else if (token == "\\use_refstyle") {
1044 lex >> use_refstyle;
1046 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1056 // Quote argument if it contains spaces
1057 string quoteIfNeeded(string const & str) {
1058 if (contains(str, ' '))
1059 return "\"" + str + "\"";
1065 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1067 // The top of the file is written by the buffer.
1068 // Prints out the buffer info into the .lyx file given by file
1070 os << "\\save_transient_properties "
1071 << convert<string>(save_transient_properties) << '\n';
1073 // the document directory (must end with a path separator)
1074 // realPath() is used to resolve symlinks, while addPath(..., "")
1075 // ensures a trailing path separator.
1077 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1078 string const sysdir = inSystemDir(FileName(filepath), docsys) ? docsys
1079 : addPath(package().system_support().realPath(), "");
1080 string const relpath =
1081 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1082 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1083 filepath = addPath("/systemlyxdir", relpath);
1084 else if (!save_transient_properties || !lyxrc.save_origin)
1085 filepath = "unavailable";
1086 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1089 os << "\\textclass "
1090 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1091 baseClass()->name()), "layout"))
1094 // then the preamble
1095 if (!preamble.empty()) {
1096 // remove '\n' from the end of preamble
1097 docstring const tmppreamble = rtrim(preamble, "\n");
1098 os << "\\begin_preamble\n"
1099 << to_utf8(tmppreamble)
1100 << "\n\\end_preamble\n";
1104 if (!options.empty()) {
1105 os << "\\options " << options << '\n';
1108 // use the class options defined in the layout?
1109 os << "\\use_default_options "
1110 << convert<string>(use_default_options) << "\n";
1112 // the master document
1113 if (!master.empty()) {
1114 os << "\\master " << master << '\n';
1118 if (!removed_modules_.empty()) {
1119 os << "\\begin_removed_modules" << '\n';
1120 list<string>::const_iterator it = removed_modules_.begin();
1121 list<string>::const_iterator en = removed_modules_.end();
1122 for (; it != en; ++it)
1124 os << "\\end_removed_modules" << '\n';
1128 if (!layout_modules_.empty()) {
1129 os << "\\begin_modules" << '\n';
1130 LayoutModuleList::const_iterator it = layout_modules_.begin();
1131 LayoutModuleList::const_iterator en = layout_modules_.end();
1132 for (; it != en; ++it)
1134 os << "\\end_modules" << '\n';
1138 if (!included_children_.empty()) {
1139 os << "\\begin_includeonly" << '\n';
1140 list<string>::const_iterator it = included_children_.begin();
1141 list<string>::const_iterator en = included_children_.end();
1142 for (; it != en; ++it)
1144 os << "\\end_includeonly" << '\n';
1146 os << "\\maintain_unincluded_children "
1147 << convert<string>(maintain_unincluded_children) << '\n';
1149 // local layout information
1150 docstring const local_layout = getLocalLayout(false);
1151 if (!local_layout.empty()) {
1152 // remove '\n' from the end
1153 docstring const tmplocal = rtrim(local_layout, "\n");
1154 os << "\\begin_local_layout\n"
1155 << to_utf8(tmplocal)
1156 << "\n\\end_local_layout\n";
1158 docstring const forced_local_layout = getLocalLayout(true);
1159 if (!forced_local_layout.empty()) {
1160 // remove '\n' from the end
1161 docstring const tmplocal = rtrim(forced_local_layout, "\n");
1162 os << "\\begin_forced_local_layout\n"
1163 << to_utf8(tmplocal)
1164 << "\n\\end_forced_local_layout\n";
1167 // then the text parameters
1168 if (language != ignore_language)
1169 os << "\\language " << language->lang() << '\n';
1170 os << "\\language_package " << lang_package
1171 << "\n\\inputencoding " << inputenc
1172 << "\n\\fontencoding " << fontenc
1173 << "\n\\font_roman \"" << fonts_roman[0]
1174 << "\" \"" << fonts_roman[1] << '"'
1175 << "\n\\font_sans \"" << fonts_sans[0]
1176 << "\" \"" << fonts_sans[1] << '"'
1177 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1178 << "\" \"" << fonts_typewriter[1] << '"'
1179 << "\n\\font_math \"" << fonts_math[0]
1180 << "\" \"" << fonts_math[1] << '"'
1181 << "\n\\font_default_family " << fonts_default_family
1182 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1183 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1184 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1185 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1186 << ' ' << fonts_sans_scale[1]
1187 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1188 << ' ' << fonts_typewriter_scale[1]
1190 if (!fonts_cjk.empty()) {
1191 os << "\\font_cjk " << fonts_cjk << '\n';
1193 os << "\\use_microtype " << convert<string>(use_microtype) << '\n';
1194 os << "\\graphics " << graphics_driver << '\n';
1195 os << "\\default_output_format " << default_output_format << '\n';
1196 os << "\\output_sync " << output_sync << '\n';
1197 if (!output_sync_macro.empty())
1198 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1199 os << "\\bibtex_command " << bibtex_command << '\n';
1200 os << "\\index_command " << index_command << '\n';
1202 if (!float_placement.empty()) {
1203 os << "\\float_placement " << float_placement << '\n';
1205 os << "\\paperfontsize " << fontsize << '\n';
1207 spacing().writeFile(os);
1208 pdfoptions().writeFile(os);
1210 os << "\\papersize " << string_papersize[papersize]
1211 << "\n\\use_geometry " << convert<string>(use_geometry);
1212 map<string, string> const & packages = auto_packages();
1213 for (map<string, string>::const_iterator it = packages.begin();
1214 it != packages.end(); ++it)
1215 os << "\n\\use_package " << it->first << ' '
1216 << use_package(it->first);
1218 os << "\n\\cite_engine ";
1220 if (!cite_engine_.empty()) {
1221 LayoutModuleList::const_iterator be = cite_engine_.begin();
1222 LayoutModuleList::const_iterator en = cite_engine_.end();
1223 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1232 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1233 << "\n\\biblio_style " << biblio_style
1234 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1235 << "\n\\use_indices " << convert<string>(use_indices)
1236 << "\n\\paperorientation " << string_orientation[orientation]
1237 << "\n\\suppress_date " << convert<string>(suppress_date)
1238 << "\n\\justification " << convert<string>(justification)
1239 << "\n\\use_refstyle " << use_refstyle
1241 if (isbackgroundcolor == true)
1242 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1243 if (isfontcolor == true)
1244 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1245 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1246 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1247 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1248 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1250 BranchList::const_iterator it = branchlist().begin();
1251 BranchList::const_iterator end = branchlist().end();
1252 for (; it != end; ++it) {
1253 os << "\\branch " << to_utf8(it->branch())
1254 << "\n\\selected " << it->isSelected()
1255 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1256 << "\n\\color " << lyx::X11hexname(it->color())
1261 IndicesList::const_iterator iit = indiceslist().begin();
1262 IndicesList::const_iterator iend = indiceslist().end();
1263 for (; iit != iend; ++iit) {
1264 os << "\\index " << to_utf8(iit->index())
1265 << "\n\\shortcut " << to_utf8(iit->shortcut())
1266 << "\n\\color " << lyx::X11hexname(iit->color())
1271 if (!paperwidth.empty())
1272 os << "\\paperwidth "
1273 << VSpace(paperwidth).asLyXCommand() << '\n';
1274 if (!paperheight.empty())
1275 os << "\\paperheight "
1276 << VSpace(paperheight).asLyXCommand() << '\n';
1277 if (!leftmargin.empty())
1278 os << "\\leftmargin "
1279 << VSpace(leftmargin).asLyXCommand() << '\n';
1280 if (!topmargin.empty())
1281 os << "\\topmargin "
1282 << VSpace(topmargin).asLyXCommand() << '\n';
1283 if (!rightmargin.empty())
1284 os << "\\rightmargin "
1285 << VSpace(rightmargin).asLyXCommand() << '\n';
1286 if (!bottommargin.empty())
1287 os << "\\bottommargin "
1288 << VSpace(bottommargin).asLyXCommand() << '\n';
1289 if (!headheight.empty())
1290 os << "\\headheight "
1291 << VSpace(headheight).asLyXCommand() << '\n';
1292 if (!headsep.empty())
1294 << VSpace(headsep).asLyXCommand() << '\n';
1295 if (!footskip.empty())
1297 << VSpace(footskip).asLyXCommand() << '\n';
1298 if (!columnsep.empty())
1299 os << "\\columnsep "
1300 << VSpace(columnsep).asLyXCommand() << '\n';
1301 os << "\\secnumdepth " << secnumdepth
1302 << "\n\\tocdepth " << tocdepth
1303 << "\n\\paragraph_separation "
1304 << string_paragraph_separation[paragraph_separation];
1305 if (!paragraph_separation)
1306 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1308 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1309 os << "\n\\quotes_style "
1310 << string_quotes_style[quotes_style]
1311 << "\n\\papercolumns " << columns
1312 << "\n\\papersides " << sides
1313 << "\n\\paperpagestyle " << pagestyle << '\n';
1314 if (!listings_params.empty())
1315 os << "\\listings_params \"" <<
1316 InsetListingsParams(listings_params).encodedString() << "\"\n";
1317 for (int i = 0; i < 4; ++i) {
1318 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1319 if (user_defined_bullet(i).getFont() != -1) {
1320 os << "\\bullet " << i << " "
1321 << user_defined_bullet(i).getFont() << " "
1322 << user_defined_bullet(i).getCharacter() << " "
1323 << user_defined_bullet(i).getSize() << "\n";
1327 os << "\\bulletLaTeX " << i << " \""
1328 << lyx::to_ascii(user_defined_bullet(i).getText())
1334 os << "\\tracking_changes "
1335 << (save_transient_properties ? convert<string>(track_changes) : "false")
1338 os << "\\output_changes "
1339 << (save_transient_properties ? convert<string>(output_changes) : "false")
1342 os << "\\html_math_output " << html_math_output << '\n'
1343 << "\\html_css_as_file " << html_css_as_file << '\n'
1344 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1346 if (html_math_img_scale != 1.0)
1347 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1348 if (!html_latex_start.empty())
1349 os << "\\html_latex_start " << html_latex_start << '\n';
1350 if (!html_latex_end.empty())
1351 os << "\\html_latex_end " << html_latex_end << '\n';
1353 os << pimpl_->authorlist;
1357 void BufferParams::validate(LaTeXFeatures & features) const
1359 features.require(documentClass().requires());
1361 if (columns > 1 && language->rightToLeft())
1362 features.require("rtloutputdblcol");
1364 if (output_changes) {
1365 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1366 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1367 LaTeXFeatures::isAvailable("xcolor");
1369 switch (features.runparams().flavor) {
1370 case OutputParams::LATEX:
1371 case OutputParams::DVILUATEX:
1373 features.require("ct-dvipost");
1374 features.require("dvipost");
1375 } else if (xcolorulem) {
1376 features.require("ct-xcolor-ulem");
1377 features.require("ulem");
1378 features.require("xcolor");
1380 features.require("ct-none");
1383 case OutputParams::LUATEX:
1384 case OutputParams::PDFLATEX:
1385 case OutputParams::XETEX:
1387 features.require("ct-xcolor-ulem");
1388 features.require("ulem");
1389 features.require("xcolor");
1390 // improves color handling in PDF output
1391 features.require("pdfcolmk");
1393 features.require("ct-none");
1401 // Floats with 'Here definitely' as default setting.
1402 if (float_placement.find('H') != string::npos)
1403 features.require("float");
1405 for (PackageMap::const_iterator it = use_packages.begin();
1406 it != use_packages.end(); ++it) {
1407 if (it->first == "amsmath") {
1408 // AMS Style is at document level
1409 if (it->second == package_on ||
1410 features.isProvided("amsmath"))
1411 features.require(it->first);
1412 } else if (it->second == package_on)
1413 features.require(it->first);
1416 // Document-level line spacing
1417 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1418 features.require("setspace");
1420 // the bullet shapes are buffer level not paragraph level
1421 // so they are tested here
1422 for (int i = 0; i < 4; ++i) {
1423 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1425 int const font = user_defined_bullet(i).getFont();
1427 int const c = user_defined_bullet(i).getCharacter();
1433 features.require("latexsym");
1435 } else if (font == 1) {
1436 features.require("amssymb");
1437 } else if (font >= 2 && font <= 5) {
1438 features.require("pifont");
1442 if (pdfoptions().use_hyperref) {
1443 features.require("hyperref");
1444 // due to interferences with babel and hyperref, the color package has to
1445 // be loaded after hyperref when hyperref is used with the colorlinks
1446 // option, see http://www.lyx.org/trac/ticket/5291
1447 if (pdfoptions().colorlinks)
1448 features.require("color");
1450 if (!listings_params.empty()) {
1451 // do not test validity because listings_params is
1452 // supposed to be valid
1454 InsetListingsParams(listings_params).separatedParams(true);
1455 // we can't support all packages, but we should load the color package
1456 if (par.find("\\color", 0) != string::npos)
1457 features.require("color");
1460 // some languages are only available via polyglossia
1461 if (features.hasPolyglossiaExclusiveLanguages())
1462 features.require("polyglossia");
1464 if (useNonTeXFonts && fontsMath() != "auto")
1465 features.require("unicode-math");
1468 features.require("microtype");
1470 if (!language->requires().empty())
1471 features.require(language->requires());
1475 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1476 FileName const & filepath) const
1478 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1479 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1480 // \RequirePackage to do so, rather than the normal \usepackage
1481 // Do not try to load any other package before the document class, unless you
1482 // have a thorough understanding of the LATEX internals and know exactly what you
1484 if (features.mustProvide("fix-cm"))
1485 os << "\\RequirePackage{fix-cm}\n";
1486 // Likewise for fixltx2e. If other packages conflict with this policy,
1487 // treat it as a package bug (and report it!)
1488 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1489 if (features.mustProvide("fixltx2e"))
1490 os << "\\RequirePackage{fixltx2e}\n";
1492 os << "\\documentclass";
1494 DocumentClass const & tclass = documentClass();
1496 ostringstream clsoptions; // the document class options.
1498 if (tokenPos(tclass.opt_fontsize(),
1499 '|', fontsize) >= 0) {
1500 // only write if existing in list (and not default)
1501 clsoptions << fontsize << "pt,";
1504 // all paper sizes except of A4, A5, B5 and the US sizes need the
1506 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1507 && papersize != PAPER_USLETTER
1508 && papersize != PAPER_USLEGAL
1509 && papersize != PAPER_USEXECUTIVE
1510 && papersize != PAPER_A4
1511 && papersize != PAPER_A5
1512 && papersize != PAPER_B5;
1514 if (!use_geometry) {
1515 switch (papersize) {
1517 clsoptions << "a4paper,";
1519 case PAPER_USLETTER:
1520 clsoptions << "letterpaper,";
1523 clsoptions << "a5paper,";
1526 clsoptions << "b5paper,";
1528 case PAPER_USEXECUTIVE:
1529 clsoptions << "executivepaper,";
1532 clsoptions << "legalpaper,";
1566 if (sides != tclass.sides()) {
1569 clsoptions << "oneside,";
1572 clsoptions << "twoside,";
1578 if (columns != tclass.columns()) {
1580 clsoptions << "twocolumn,";
1582 clsoptions << "onecolumn,";
1586 && orientation == ORIENTATION_LANDSCAPE)
1587 clsoptions << "landscape,";
1589 // language should be a parameter to \documentclass
1590 if (language->babel() == "hebrew"
1591 && default_language->babel() != "hebrew")
1592 // This seems necessary
1593 features.useLanguage(default_language);
1595 ostringstream language_options;
1596 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1597 bool const use_polyglossia = features.usePolyglossia();
1598 bool const global = lyxrc.language_global_options;
1599 if (use_babel || (use_polyglossia && global)) {
1600 language_options << features.getBabelLanguages();
1601 if (!language->babel().empty()) {
1602 if (!language_options.str().empty())
1603 language_options << ',';
1604 language_options << language->babel();
1606 if (global && !features.needBabelLangOptions()
1607 && !language_options.str().empty())
1608 clsoptions << language_options.str() << ',';
1611 // the predefined options from the layout
1612 if (use_default_options && !tclass.options().empty())
1613 clsoptions << tclass.options() << ',';
1615 // the user-defined options
1616 if (!options.empty()) {
1617 clsoptions << options << ',';
1620 string strOptions(clsoptions.str());
1621 if (!strOptions.empty()) {
1622 strOptions = rtrim(strOptions, ",");
1624 os << '[' << from_utf8(strOptions) << ']';
1627 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1628 // end of \documentclass defs
1630 // if we use fontspec or newtxmath, we have to load the AMS packages here
1631 string const ams = features.loadAMSPackages();
1632 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1633 bool const use_newtxmath =
1634 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1635 ot1, false, false) == "newtxmath";
1636 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1637 os << from_ascii(ams);
1639 if (useNonTeXFonts) {
1640 if (!features.isProvided("fontspec"))
1641 os << "\\usepackage{fontspec}\n";
1642 if (features.mustProvide("unicode-math")
1643 && features.isAvailable("unicode-math"))
1644 os << "\\usepackage{unicode-math}\n";
1647 // font selection must be done before loading fontenc.sty
1648 string const fonts = loadFonts(features);
1650 os << from_utf8(fonts);
1652 if (fonts_default_family != "default")
1653 os << "\\renewcommand{\\familydefault}{\\"
1654 << from_ascii(fonts_default_family) << "}\n";
1656 // set font encoding
1657 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1658 if (!useNonTeXFonts && !features.isProvided("fontenc")
1659 && font_encoding() != "default") {
1660 // get main font encodings
1661 vector<string> fontencs = font_encodings();
1662 // get font encodings of secondary languages
1663 features.getFontEncodings(fontencs);
1664 if (!fontencs.empty()) {
1665 os << "\\usepackage["
1666 << from_ascii(getStringFromVector(fontencs))
1671 // handle inputenc etc.
1672 writeEncodingPreamble(os, features);
1675 if (!features.runparams().includeall && !included_children_.empty()) {
1676 os << "\\includeonly{";
1677 list<string>::const_iterator it = included_children_.begin();
1678 list<string>::const_iterator en = included_children_.end();
1680 for (; it != en; ++it) {
1681 string incfile = *it;
1682 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1683 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1685 if (!features.runparams().nice)
1687 // \includeonly doesn't want an extension
1688 incfile = changeExtension(incfile, string());
1689 incfile = support::latex_path(incfile);
1690 if (!incfile.empty()) {
1693 os << from_utf8(incfile);
1700 if (!features.isProvided("geometry")
1701 && (use_geometry || nonstandard_papersize)) {
1702 odocstringstream ods;
1703 if (!getGraphicsDriver("geometry").empty())
1704 ods << getGraphicsDriver("geometry");
1705 if (orientation == ORIENTATION_LANDSCAPE)
1706 ods << ",landscape";
1707 switch (papersize) {
1709 if (!paperwidth.empty())
1710 ods << ",paperwidth="
1711 << from_ascii(paperwidth);
1712 if (!paperheight.empty())
1713 ods << ",paperheight="
1714 << from_ascii(paperheight);
1716 case PAPER_USLETTER:
1717 ods << ",letterpaper";
1720 ods << ",legalpaper";
1722 case PAPER_USEXECUTIVE:
1723 ods << ",executivepaper";
1812 docstring const g_options = trim(ods.str(), ",");
1813 os << "\\usepackage";
1814 if (!g_options.empty())
1815 os << '[' << g_options << ']';
1816 os << "{geometry}\n";
1817 // output this only if use_geometry is true
1819 os << "\\geometry{verbose";
1820 if (!topmargin.empty())
1821 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1822 if (!bottommargin.empty())
1823 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1824 if (!leftmargin.empty())
1825 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1826 if (!rightmargin.empty())
1827 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1828 if (!headheight.empty())
1829 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1830 if (!headsep.empty())
1831 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1832 if (!footskip.empty())
1833 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1834 if (!columnsep.empty())
1835 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1838 } else if (orientation == ORIENTATION_LANDSCAPE
1839 || papersize != PAPER_DEFAULT) {
1840 features.require("papersize");
1843 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1844 if (pagestyle == "fancy")
1845 os << "\\usepackage{fancyhdr}\n";
1846 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1849 // only output when the background color is not default
1850 if (isbackgroundcolor == true) {
1851 // only require color here, the background color will be defined
1852 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1854 features.require("color");
1855 features.require("pagecolor");
1858 // only output when the font color is not default
1859 if (isfontcolor == true) {
1860 // only require color here, the font color will be defined
1861 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1863 features.require("color");
1864 features.require("fontcolor");
1867 // Only if class has a ToC hierarchy
1868 if (tclass.hasTocLevels()) {
1869 if (secnumdepth != tclass.secnumdepth()) {
1870 os << "\\setcounter{secnumdepth}{"
1874 if (tocdepth != tclass.tocdepth()) {
1875 os << "\\setcounter{tocdepth}{"
1881 if (paragraph_separation) {
1882 // when skip separation
1883 switch (getDefSkip().kind()) {
1884 case VSpace::SMALLSKIP:
1885 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1887 case VSpace::MEDSKIP:
1888 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1890 case VSpace::BIGSKIP:
1891 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1893 case VSpace::LENGTH:
1894 os << "\\setlength{\\parskip}{"
1895 << from_utf8(getDefSkip().length().asLatexString())
1898 default: // should never happen // Then delete it.
1899 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1902 os << "\\setlength{\\parindent}{0pt}\n";
1904 // when separation by indentation
1905 // only output something when a width is given
1906 if (getIndentation().asLyXCommand() != "default") {
1907 os << "\\setlength{\\parindent}{"
1908 << from_utf8(getIndentation().asLatexCommand())
1913 // Now insert the LyX specific LaTeX commands...
1914 features.resolveAlternatives();
1915 features.expandMultiples();
1918 if (!output_sync_macro.empty())
1919 os << from_utf8(output_sync_macro) +"\n";
1920 else if (features.runparams().flavor == OutputParams::LATEX)
1921 os << "\\usepackage[active]{srcltx}\n";
1922 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1923 os << "\\synctex=-1\n";
1926 // The package options (via \PassOptionsToPackage)
1927 os << from_ascii(features.getPackageOptions());
1929 // due to interferences with babel and hyperref, the color package has to
1930 // be loaded (when it is not already loaded) before babel when hyperref
1931 // is used with the colorlinks option, see
1932 // http://www.lyx.org/trac/ticket/5291
1933 // we decided therefore to load color always before babel, see
1934 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1935 os << from_ascii(features.getColorOptions());
1937 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1938 // we have to call babel before
1940 && (features.isRequired("jurabib")
1941 || features.isRequired("hyperref")
1942 || features.isRequired("varioref")
1943 || features.isRequired("vietnamese")
1944 || features.isRequired("japanese"))) {
1945 os << features.getBabelPresettings();
1947 os << from_utf8(babelCall(language_options.str(),
1948 features.needBabelLangOptions())) + '\n';
1949 os << features.getBabelPostsettings();
1952 // The optional packages;
1953 os << from_ascii(features.getPackages());
1955 // Additional Indices
1956 if (features.isRequired("splitidx")) {
1957 IndicesList::const_iterator iit = indiceslist().begin();
1958 IndicesList::const_iterator iend = indiceslist().end();
1959 for (; iit != iend; ++iit) {
1960 pair<docstring, docstring> indexname_latex =
1961 features.runparams().encoding->latexString(iit->index(),
1962 features.runparams().dryrun);
1963 if (!indexname_latex.second.empty()) {
1964 // issue a warning about omitted characters
1965 // FIXME: should be passed to the error dialog
1966 frontend::Alert::warning(_("Uncodable characters"),
1967 bformat(_("The following characters that are used in an index name are not\n"
1968 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1969 indexname_latex.second));
1971 os << "\\newindex[";
1972 os << indexname_latex.first;
1974 os << escape(iit->shortcut());
1980 os << from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1983 // * Hyperref manual: "Make sure it comes last of your loaded
1984 // packages, to give it a fighting chance of not being over-written,
1985 // since its job is to redefine many LaTeX commands."
1986 // * Email from Heiko Oberdiek: "It is usually better to load babel
1987 // before hyperref. Then hyperref has a chance to detect babel.
1988 // * Has to be loaded before the "LyX specific LaTeX commands" to
1989 // avoid errors with algorithm floats.
1990 // use hyperref explicitly if it is required
1991 if (features.isRequired("hyperref")) {
1992 OutputParams tmp_params = features.runparams();
1993 pdfoptions().writeLaTeX(tmp_params, os,
1994 features.isProvided("hyperref"));
1995 // correctly break URLs with hyperref and dvi output
1996 if (features.runparams().flavor == OutputParams::LATEX
1997 && features.isAvailable("breakurl"))
1998 os << "\\usepackage{breakurl}\n";
1999 } else if (features.isRequired("nameref"))
2000 // hyperref loads this automatically
2001 os << "\\usepackage{nameref}\n";
2003 // bibtopic needs to be loaded after hyperref.
2004 // the dot provides the aux file naming which LyX can detect.
2005 if (features.mustProvide("bibtopic"))
2006 os << "\\usepackage[dot]{bibtopic}\n";
2008 // Will be surrounded by \makeatletter and \makeatother when not empty
2009 otexstringstream atlyxpreamble;
2011 // Some macros LyX will need
2013 TexString tmppreamble = features.getMacros();
2014 if (!tmppreamble.str.empty())
2015 atlyxpreamble << "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2016 "LyX specific LaTeX commands.\n"
2017 << move(tmppreamble)
2020 // the text class specific preamble
2022 docstring tmppreamble = features.getTClassPreamble();
2023 if (!tmppreamble.empty())
2024 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2025 "Textclass specific LaTeX commands.\n"
2029 // suppress date if selected
2030 // use \@ifundefined because we cannot be sure that every document class
2031 // has a \date command
2033 atlyxpreamble << "\\@ifundefined{date}{}{\\date{}}\n";
2035 /* the user-defined preamble */
2036 if (!containsOnly(preamble, " \n\t")) {
2038 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2039 "User specified LaTeX commands.\n";
2041 // Check if the user preamble contains uncodable glyphs
2042 odocstringstream user_preamble;
2043 docstring uncodable_glyphs;
2044 Encoding const * const enc = features.runparams().encoding;
2046 for (size_t n = 0; n < preamble.size(); ++n) {
2047 char_type c = preamble[n];
2048 if (!enc->encodable(c)) {
2049 docstring const glyph(1, c);
2050 LYXERR0("Uncodable character '"
2052 << "' in user preamble!");
2053 uncodable_glyphs += glyph;
2054 if (features.runparams().dryrun) {
2055 user_preamble << "<" << _("LyX Warning: ")
2056 << _("uncodable character") << " '";
2057 user_preamble.put(c);
2058 user_preamble << "'>";
2061 user_preamble.put(c);
2064 user_preamble << preamble;
2066 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2067 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2068 frontend::Alert::warning(
2069 _("Uncodable character in user preamble"),
2071 _("The user preamble of your document contains glyphs "
2072 "that are unknown in the current document encoding "
2073 "(namely %1$s).\nThese glyphs are omitted "
2074 " from the output, which may result in "
2075 "incomplete output."
2076 "\n\nPlease select an appropriate "
2077 "document encoding\n"
2078 "(such as utf8) or change the "
2079 "preamble code accordingly."),
2082 atlyxpreamble << user_preamble.str() << '\n';
2085 // footmisc must be loaded after setspace
2086 // Load it here to avoid clashes with footmisc loaded in the user
2087 // preamble. For that reason we also pass the options via
2088 // \PassOptionsToPackage in getPreamble() and not here.
2089 if (features.mustProvide("footmisc"))
2090 atlyxpreamble << "\\usepackage{footmisc}\n";
2092 // subfig loads internally the LaTeX package "caption". As
2093 // caption is a very popular package, users will load it in
2094 // the preamble. Therefore we must load subfig behind the
2095 // user-defined preamble and check if the caption package was
2096 // loaded or not. For the case that caption is loaded before
2097 // subfig, there is the subfig option "caption=false". This
2098 // option also works when a koma-script class is used and
2099 // koma's own caption commands are used instead of caption. We
2100 // use \PassOptionsToPackage here because the user could have
2101 // already loaded subfig in the preamble.
2102 if (features.mustProvide("subfig"))
2103 atlyxpreamble << "\\@ifundefined{showcaptionsetup}{}{%\n"
2104 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2105 "\\usepackage{subfig}\n";
2107 // Itemize bullet settings need to be last in case the user
2108 // defines their own bullets that use a package included
2109 // in the user-defined preamble -- ARRae
2110 // Actually it has to be done much later than that
2111 // since some packages like frenchb make modifications
2112 // at \begin{document} time -- JMarc
2113 docstring bullets_def;
2114 for (int i = 0; i < 4; ++i) {
2115 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2116 if (bullets_def.empty())
2117 bullets_def += "\\AtBeginDocument{\n";
2118 bullets_def += " \\def\\labelitemi";
2120 // `i' is one less than the item to modify
2127 bullets_def += "ii";
2133 bullets_def += '{' +
2134 user_defined_bullet(i).getText()
2139 if (!bullets_def.empty())
2140 atlyxpreamble << bullets_def << "}\n\n";
2142 if (!atlyxpreamble.empty())
2143 os << "\n\\makeatletter\n"
2144 << atlyxpreamble.release()
2145 << "\\makeatother\n\n";
2147 // We try to load babel late, in case it interferes with other packages.
2148 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2149 // called after babel, though.
2150 if (use_babel && !features.isRequired("jurabib")
2151 && !features.isRequired("hyperref")
2152 && !features.isRequired("varioref")
2153 && !features.isRequired("vietnamese")
2154 && !features.isRequired("japanese")) {
2155 os << features.getBabelPresettings();
2157 os << from_utf8(babelCall(language_options.str(),
2158 features.needBabelLangOptions())) + '\n';
2159 os << features.getBabelPostsettings();
2161 if (features.isRequired("bicaption"))
2162 os << "\\usepackage{bicaption}\n";
2163 if (!listings_params.empty() || features.mustProvide("listings"))
2164 os << "\\usepackage{listings}\n";
2165 if (!listings_params.empty()) {
2167 // do not test validity because listings_params is
2168 // supposed to be valid
2170 InsetListingsParams(listings_params).separatedParams(true);
2171 os << from_utf8(par);
2175 // xunicode needs to be loaded at least after amsmath, amssymb,
2176 // esint and the other packages that provide special glyphs
2177 // The package only supports XeTeX currently.
2178 if (features.runparams().flavor == OutputParams::XETEX
2180 os << "\\usepackage{xunicode}\n";
2182 // Polyglossia must be loaded last
2183 if (use_polyglossia) {
2185 os << "\\usepackage{polyglossia}\n";
2186 // set the main language
2187 os << "\\setdefaultlanguage";
2188 if (!language->polyglossiaOpts().empty())
2189 os << "[" << from_ascii(language->polyglossiaOpts()) << "]";
2190 os << "{" << from_ascii(language->polyglossia()) << "}\n";
2191 // now setup the other languages
2192 set<string> const polylangs =
2193 features.getPolyglossiaLanguages();
2194 for (set<string>::const_iterator mit = polylangs.begin();
2195 mit != polylangs.end() ; ++mit) {
2196 // We do not output the options here; they are output in
2197 // the language switch commands. This is safer if multiple
2198 // varieties are used.
2199 if (*mit == language->polyglossia())
2201 os << "\\setotherlanguage";
2202 os << "{" << from_ascii(*mit) << "}\n";
2206 // Load custom language package here
2207 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2208 if (lang_package == "default")
2209 os << from_utf8(lyxrc.language_custom_package);
2211 os << from_utf8(lang_package);
2215 docstring const i18npreamble =
2216 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2217 if (!i18npreamble.empty())
2218 os << i18npreamble + '\n';
2224 void BufferParams::useClassDefaults()
2226 DocumentClass const & tclass = documentClass();
2228 sides = tclass.sides();
2229 columns = tclass.columns();
2230 pagestyle = tclass.pagestyle();
2231 use_default_options = true;
2232 // Only if class has a ToC hierarchy
2233 if (tclass.hasTocLevels()) {
2234 secnumdepth = tclass.secnumdepth();
2235 tocdepth = tclass.tocdepth();
2240 bool BufferParams::hasClassDefaults() const
2242 DocumentClass const & tclass = documentClass();
2244 return sides == tclass.sides()
2245 && columns == tclass.columns()
2246 && pagestyle == tclass.pagestyle()
2247 && use_default_options
2248 && secnumdepth == tclass.secnumdepth()
2249 && tocdepth == tclass.tocdepth();
2253 DocumentClass const & BufferParams::documentClass() const
2259 DocumentClassConstPtr BufferParams::documentClassPtr() const
2265 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2267 // evil, but this function is evil
2268 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2269 invalidateConverterCache();
2273 bool BufferParams::setBaseClass(string const & classname)
2275 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2276 LayoutFileList & bcl = LayoutFileList::get();
2277 if (!bcl.haveClass(classname)) {
2279 bformat(_("The layout file:\n"
2281 "could not be found. A default textclass with default\n"
2282 "layouts will be used. LyX will not be able to produce\n"
2284 from_utf8(classname));
2285 frontend::Alert::error(_("Document class not found"), s);
2286 bcl.addEmptyClass(classname);
2289 bool const success = bcl[classname].load();
2292 bformat(_("Due to some error in it, the layout file:\n"
2294 "could not be loaded. A default textclass with default\n"
2295 "layouts will be used. LyX will not be able to produce\n"
2297 from_utf8(classname));
2298 frontend::Alert::error(_("Could not load class"), s);
2299 bcl.addEmptyClass(classname);
2302 pimpl_->baseClass_ = classname;
2303 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2308 LayoutFile const * BufferParams::baseClass() const
2310 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2311 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2317 LayoutFileIndex const & BufferParams::baseClassID() const
2319 return pimpl_->baseClass_;
2323 void BufferParams::makeDocumentClass(bool const clone)
2328 invalidateConverterCache();
2329 LayoutModuleList mods;
2330 LayoutModuleList::iterator it = layout_modules_.begin();
2331 LayoutModuleList::iterator en = layout_modules_.end();
2332 for (; it != en; ++it)
2333 mods.push_back(*it);
2335 it = cite_engine_.begin();
2336 en = cite_engine_.end();
2337 for (; it != en; ++it)
2338 mods.push_back(*it);
2340 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2342 TextClass::ReturnValues success = TextClass::OK;
2343 if (!forced_local_layout_.empty())
2344 success = doc_class_->read(to_utf8(forced_local_layout_),
2346 if (!local_layout_.empty() &&
2347 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2348 success = doc_class_->read(to_utf8(local_layout_), TextClass::MODULE);
2349 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2350 docstring const msg = _("Error reading internal layout information");
2351 frontend::Alert::warning(_("Read Error"), msg);
2356 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2358 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2362 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2364 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2368 docstring BufferParams::getLocalLayout(bool forced) const
2371 return from_utf8(doc_class_->forcedLayouts());
2373 return local_layout_;
2377 void BufferParams::setLocalLayout(docstring const & layout, bool forced)
2380 forced_local_layout_ = layout;
2382 local_layout_ = layout;
2386 bool BufferParams::addLayoutModule(string const & modName)
2388 LayoutModuleList::const_iterator it = layout_modules_.begin();
2389 LayoutModuleList::const_iterator end = layout_modules_.end();
2390 for (; it != end; ++it)
2393 layout_modules_.push_back(modName);
2398 string BufferParams::bufferFormat() const
2400 return documentClass().outputFormat();
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 (encoding().package() == Encoding::japanese)
2455 v.push_back("platex");
2457 if (!useNonTeXFonts) {
2458 v.push_back("pdflatex");
2459 v.push_back("latex");
2461 v.push_back("xetex");
2462 v.push_back("luatex");
2463 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 InsetQuotesParams::QuoteStyle BufferParams::getQuoteStyle(string const & qs) const
2559 return quotesstyletranslator().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(from_ascii("\\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(from_ascii("\\end_forced_local_layout"));
2603 local_layout_ = lex.getLongString(from_ascii("\\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;