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_language[] = {
75 "english", "swedish", "german", "polish", "french", "danish", ""
79 static char const * const string_papersize[] = {
80 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
81 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
82 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
83 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
84 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
89 static char const * const string_orientation[] = {
90 "portrait", "landscape", ""
94 static char const * const tex_graphics[] = {
95 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
96 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
97 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
98 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
109 // Paragraph separation
110 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
113 ParSepTranslator const init_parseptranslator()
115 ParSepTranslator translator
116 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
117 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
122 ParSepTranslator const & parseptranslator()
124 static ParSepTranslator const translator =
125 init_parseptranslator();
131 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
134 QuotesLangTranslator const init_quoteslangtranslator()
136 QuotesLangTranslator translator
137 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
138 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
139 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
140 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
141 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
142 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
147 QuotesLangTranslator const & quoteslangtranslator()
149 static QuotesLangTranslator const translator =
150 init_quoteslangtranslator();
156 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
159 static PaperSizeTranslator initPaperSizeTranslator()
161 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
162 translator.addPair(string_papersize[1], PAPER_CUSTOM);
163 translator.addPair(string_papersize[2], PAPER_USLETTER);
164 translator.addPair(string_papersize[3], PAPER_USLEGAL);
165 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
166 translator.addPair(string_papersize[5], PAPER_A0);
167 translator.addPair(string_papersize[6], PAPER_A1);
168 translator.addPair(string_papersize[7], PAPER_A2);
169 translator.addPair(string_papersize[8], PAPER_A3);
170 translator.addPair(string_papersize[9], PAPER_A4);
171 translator.addPair(string_papersize[10], PAPER_A5);
172 translator.addPair(string_papersize[11], PAPER_A6);
173 translator.addPair(string_papersize[12], PAPER_B0);
174 translator.addPair(string_papersize[13], PAPER_B1);
175 translator.addPair(string_papersize[14], PAPER_B2);
176 translator.addPair(string_papersize[15], PAPER_B3);
177 translator.addPair(string_papersize[16], PAPER_B4);
178 translator.addPair(string_papersize[17], PAPER_B5);
179 translator.addPair(string_papersize[18], PAPER_B6);
180 translator.addPair(string_papersize[19], PAPER_C0);
181 translator.addPair(string_papersize[20], PAPER_C1);
182 translator.addPair(string_papersize[21], PAPER_C2);
183 translator.addPair(string_papersize[22], PAPER_C3);
184 translator.addPair(string_papersize[23], PAPER_C4);
185 translator.addPair(string_papersize[24], PAPER_C5);
186 translator.addPair(string_papersize[25], PAPER_C6);
187 translator.addPair(string_papersize[26], PAPER_JISB0);
188 translator.addPair(string_papersize[27], PAPER_JISB1);
189 translator.addPair(string_papersize[28], PAPER_JISB2);
190 translator.addPair(string_papersize[29], PAPER_JISB3);
191 translator.addPair(string_papersize[30], PAPER_JISB4);
192 translator.addPair(string_papersize[31], PAPER_JISB5);
193 translator.addPair(string_papersize[32], PAPER_JISB6);
198 PaperSizeTranslator const & papersizetranslator()
200 static PaperSizeTranslator const translator =
201 initPaperSizeTranslator();
207 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
210 PaperOrientationTranslator const init_paperorientationtranslator()
212 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
213 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
218 PaperOrientationTranslator const & paperorientationtranslator()
220 static PaperOrientationTranslator const translator =
221 init_paperorientationtranslator();
227 typedef Translator<int, PageSides> SidesTranslator;
230 SidesTranslator const init_sidestranslator()
232 SidesTranslator translator(1, OneSide);
233 translator.addPair(2, TwoSides);
238 SidesTranslator const & sidestranslator()
240 static SidesTranslator const translator = init_sidestranslator();
246 typedef Translator<int, BufferParams::Package> PackageTranslator;
249 PackageTranslator const init_packagetranslator()
251 PackageTranslator translator(0, BufferParams::package_off);
252 translator.addPair(1, BufferParams::package_auto);
253 translator.addPair(2, BufferParams::package_on);
258 PackageTranslator const & packagetranslator()
260 static PackageTranslator const translator =
261 init_packagetranslator();
267 typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
270 CiteEngineTypeTranslator const init_citeenginetypetranslator()
272 CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
273 translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
274 translator.addPair("default", ENGINE_TYPE_DEFAULT);
279 CiteEngineTypeTranslator const & citeenginetypetranslator()
281 static CiteEngineTypeTranslator const translator =
282 init_citeenginetypetranslator();
288 typedef Translator<string, Spacing::Space> SpaceTranslator;
291 SpaceTranslator const init_spacetranslator()
293 SpaceTranslator translator("default", Spacing::Default);
294 translator.addPair("single", Spacing::Single);
295 translator.addPair("onehalf", Spacing::Onehalf);
296 translator.addPair("double", Spacing::Double);
297 translator.addPair("other", Spacing::Other);
302 SpaceTranslator const & spacetranslator()
304 static SpaceTranslator const translator = init_spacetranslator();
309 bool inSystemDir(FileName const & document_dir, string & system_dir)
311 // A document is assumed to be in a system LyX directory (not
312 // necessarily the system directory of the running instance)
313 // if both "configure.py" and "chkconfig.ltx" are found in
314 // either document_dir/../ or document_dir/../../.
315 // If true, the system directory path is returned in system_dir
316 // with a trailing path separator.
318 string const msg = "Checking whether document is in a system dir...";
320 string dir = document_dir.absFileName();
322 for (int i = 0; i < 2; ++i) {
323 dir = addPath(dir, "..");
324 if (!fileSearch(dir, "configure.py").empty() &&
325 !fileSearch(dir, "chkconfig.ltx").empty()) {
326 LYXERR(Debug::FILES, msg << " yes");
327 system_dir = addPath(FileName(dir).realPath(), "");
332 LYXERR(Debug::FILES, msg << " no");
333 system_dir = string();
340 class BufferParams::Impl
345 AuthorList authorlist;
346 BranchList branchlist;
347 Bullet temp_bullets[4];
348 Bullet user_defined_bullets[4];
349 IndicesList indiceslist;
351 /** This is the amount of space used for paragraph_separation "skip",
352 * and for detached paragraphs in "indented" documents.
356 PDFOptions pdfoptions;
357 LayoutFileIndex baseClass_;
358 FormatList exportableFormatList;
359 FormatList viewableFormatList;
360 bool isViewCacheValid;
361 bool isExportCacheValid;
365 BufferParams::Impl::Impl()
366 : defskip(VSpace::MEDSKIP), baseClass_(string("")),
367 isViewCacheValid(false), isExportCacheValid(false)
369 // set initial author
371 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
376 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
379 return new BufferParams::Impl(*ptr);
383 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
389 BufferParams::BufferParams()
392 setBaseClass(defaultBaseclass());
393 cite_engine_.push_back("basic");
394 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
396 paragraph_separation = ParagraphIndentSeparation;
397 quotes_language = InsetQuotes::EnglishQuotes;
398 fontsize = "default";
401 papersize = PAPER_DEFAULT;
402 orientation = ORIENTATION_PORTRAIT;
403 use_geometry = false;
404 biblio_style = "plain";
405 use_bibtopic = false;
407 save_transient_properties = true;
408 track_changes = false;
409 output_changes = false;
410 use_default_options = true;
411 maintain_unincluded_children = false;
414 language = default_language;
416 fonts_roman[0] = "default";
417 fonts_roman[1] = "default";
418 fonts_sans[0] = "default";
419 fonts_sans[1] = "default";
420 fonts_typewriter[0] = "default";
421 fonts_typewriter[1] = "default";
422 fonts_math[0] = "auto";
423 fonts_math[1] = "auto";
424 fonts_default_family = "default";
425 useNonTeXFonts = false;
426 use_microtype = false;
427 fonts_expert_sc = false;
428 fonts_old_figures = false;
429 fonts_sans_scale[0] = 100;
430 fonts_sans_scale[1] = 100;
431 fonts_typewriter_scale[0] = 100;
432 fonts_typewriter_scale[1] = 100;
434 lang_package = "default";
435 graphics_driver = "default";
436 default_output_format = "default";
437 bibtex_command = "default";
438 index_command = "default";
441 listings_params = string();
442 pagestyle = "default";
443 suppress_date = false;
444 justification = true;
445 // no color is the default (white)
446 backgroundcolor = lyx::rgbFromHexName("#ffffff");
447 isbackgroundcolor = false;
448 // no color is the default (black)
449 fontcolor = lyx::rgbFromHexName("#000000");
451 // light gray is the default font color for greyed-out notes
452 notefontcolor = lyx::rgbFromHexName("#cccccc");
453 boxbgcolor = lyx::rgbFromHexName("#ff0000");
454 compressed = lyxrc.save_compressed;
455 for (int iter = 0; iter < 4; ++iter) {
456 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
457 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
460 indiceslist().addDefault(B_("Index"));
461 html_be_strict = false;
462 html_math_output = MathML;
463 html_math_img_scale = 1.0;
464 html_css_as_file = false;
465 display_pixel_ratio = 1.0;
470 // map current author
471 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
475 docstring BufferParams::B_(string const & l10n) const
477 LASSERT(language, return from_utf8(l10n));
478 return getMessages(language->code()).get(l10n);
482 BufferParams::Package BufferParams::use_package(std::string const & p) const
484 PackageMap::const_iterator it = use_packages.find(p);
485 if (it == use_packages.end())
491 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
497 map<string, string> const & BufferParams::auto_packages()
499 static map<string, string> packages;
500 if (packages.empty()) {
501 // We could have a race condition here that two threads
502 // discover an empty map at the same time and want to fill
503 // it, but that is no problem, since the same contents is
504 // filled in twice then. Having the locker inside the
505 // packages.empty() condition has the advantage that we
506 // don't need the mutex overhead for simple reading.
508 Mutex::Locker locker(&mutex);
509 // adding a package here implies a file format change!
510 packages["amsmath"] =
511 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
512 packages["amssymb"] =
513 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
515 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
517 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
518 packages["mathdots"] =
519 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
520 packages["mathtools"] =
521 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
523 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
524 packages["stackrel"] =
525 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
526 packages["stmaryrd"] =
527 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");
528 packages["undertilde"] =
529 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
535 AuthorList & BufferParams::authors()
537 return pimpl_->authorlist;
541 AuthorList const & BufferParams::authors() const
543 return pimpl_->authorlist;
547 void BufferParams::addAuthor(Author a)
549 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
553 BranchList & BufferParams::branchlist()
555 return pimpl_->branchlist;
559 BranchList const & BufferParams::branchlist() const
561 return pimpl_->branchlist;
565 IndicesList & BufferParams::indiceslist()
567 return pimpl_->indiceslist;
571 IndicesList const & BufferParams::indiceslist() const
573 return pimpl_->indiceslist;
577 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
579 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
580 return pimpl_->temp_bullets[index];
584 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
586 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
587 return pimpl_->temp_bullets[index];
591 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
593 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
594 return pimpl_->user_defined_bullets[index];
598 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
600 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
601 return pimpl_->user_defined_bullets[index];
605 Spacing & BufferParams::spacing()
607 return pimpl_->spacing;
611 Spacing const & BufferParams::spacing() const
613 return pimpl_->spacing;
617 PDFOptions & BufferParams::pdfoptions()
619 return pimpl_->pdfoptions;
623 PDFOptions const & BufferParams::pdfoptions() const
625 return pimpl_->pdfoptions;
629 HSpace const & BufferParams::getIndentation() const
631 return pimpl_->indentation;
635 void BufferParams::setIndentation(HSpace const & indent)
637 pimpl_->indentation = indent;
641 VSpace const & BufferParams::getDefSkip() const
643 return pimpl_->defskip;
647 void BufferParams::setDefSkip(VSpace const & vs)
649 // DEFSKIP will cause an infinite loop
650 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
651 pimpl_->defskip = vs;
655 string BufferParams::readToken(Lexer & lex, string const & token,
656 FileName const & filepath)
660 if (token == "\\textclass") {
662 string const classname = lex.getString();
663 // if there exists a local layout file, ignore the system one
664 // NOTE: in this case, the textclass (.cls file) is assumed to
667 LayoutFileList & bcl = LayoutFileList::get();
668 if (!filepath.empty()) {
669 // If classname is an absolute path, the document is
670 // using a local layout file which could not be accessed
671 // by a relative path. In this case the path is correct
672 // even if the document was moved to a different
673 // location. However, we will have a problem if the
674 // document was generated on a different platform.
675 bool isabsolute = FileName::isAbsolute(classname);
676 string const classpath = onlyPath(classname);
677 string const path = isabsolute ? classpath
678 : FileName(addPath(filepath.absFileName(),
679 classpath)).realPath();
680 string const oldpath = isabsolute ? string()
681 : FileName(addPath(origin, classpath)).realPath();
682 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
684 // that returns non-empty if a "local" layout file is found.
686 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
687 from_utf8(filepath.absFileName())));
690 setBaseClass(onlyFileName(tcp));
692 setBaseClass(onlyFileName(classname));
693 // We assume that a tex class exists for local or unknown
694 // layouts so this warning, will only be given for system layouts.
695 if (!baseClass()->isTeXClassAvailable()) {
696 docstring const desc =
697 translateIfPossible(from_utf8(baseClass()->description()));
698 docstring const prereqs =
699 from_utf8(baseClass()->prerequisites());
700 docstring const msg =
701 bformat(_("The selected document class\n"
703 "requires external files that are not available.\n"
704 "The document class can still be used, but the\n"
705 "document cannot be compiled until the following\n"
706 "prerequisites are installed:\n"
708 "See section 3.1.2.2 (Class Availability) of the\n"
709 "User's Guide for more information."), desc, prereqs);
710 frontend::Alert::warning(_("Document class not available"),
713 } else if (token == "\\save_transient_properties") {
714 lex >> save_transient_properties;
715 } else if (token == "\\origin") {
717 origin = lex.getString();
718 string const sysdirprefix = "/systemlyxdir/";
719 if (prefixIs(origin, sysdirprefix)) {
721 if (inSystemDir(filepath, docsys))
722 origin.replace(0, sysdirprefix.length() - 1, docsys);
724 origin.replace(0, sysdirprefix.length() - 1,
725 package().system_support().absFileName());
727 } else if (token == "\\begin_preamble") {
729 } else if (token == "\\begin_local_layout") {
730 readLocalLayout(lex, false);
731 } else if (token == "\\begin_forced_local_layout") {
732 readLocalLayout(lex, true);
733 } else if (token == "\\begin_modules") {
735 } else if (token == "\\begin_removed_modules") {
736 readRemovedModules(lex);
737 } else if (token == "\\begin_includeonly") {
738 readIncludeonly(lex);
739 } else if (token == "\\maintain_unincluded_children") {
740 lex >> maintain_unincluded_children;
741 } else if (token == "\\options") {
743 options = lex.getString();
744 } else if (token == "\\use_default_options") {
745 lex >> use_default_options;
746 } else if (token == "\\master") {
748 master = lex.getString();
749 if (!filepath.empty() && FileName::isAbsolute(origin)) {
750 bool const isabs = FileName::isAbsolute(master);
751 FileName const abspath(isabs ? master : origin + master);
752 bool const moved = filepath != FileName(origin);
753 if (moved && abspath.exists()) {
754 docstring const path = isabs
756 : from_utf8(abspath.realPath());
757 docstring const refpath =
758 from_utf8(filepath.absFileName());
759 master = to_utf8(makeRelPath(path, refpath));
762 } else if (token == "\\suppress_date") {
763 lex >> suppress_date;
764 } else if (token == "\\justification") {
765 lex >> justification;
766 } else if (token == "\\language") {
768 } else if (token == "\\language_package") {
770 lang_package = lex.getString();
771 } else if (token == "\\inputencoding") {
773 } else if (token == "\\graphics") {
774 readGraphicsDriver(lex);
775 } else if (token == "\\default_output_format") {
776 lex >> default_output_format;
777 } else if (token == "\\bibtex_command") {
779 bibtex_command = lex.getString();
780 } else if (token == "\\index_command") {
782 index_command = lex.getString();
783 } else if (token == "\\fontencoding") {
785 fontenc = lex.getString();
786 } else if (token == "\\font_roman") {
787 lex >> fonts_roman[0];
788 lex >> fonts_roman[1];
789 } else if (token == "\\font_sans") {
790 lex >> fonts_sans[0];
791 lex >> fonts_sans[1];
792 } else if (token == "\\font_typewriter") {
793 lex >> fonts_typewriter[0];
794 lex >> fonts_typewriter[1];
795 } else if (token == "\\font_math") {
796 lex >> fonts_math[0];
797 lex >> fonts_math[1];
798 } else if (token == "\\font_default_family") {
799 lex >> fonts_default_family;
800 } else if (token == "\\use_non_tex_fonts") {
801 lex >> useNonTeXFonts;
802 } else if (token == "\\font_sc") {
803 lex >> fonts_expert_sc;
804 } else if (token == "\\font_osf") {
805 lex >> fonts_old_figures;
806 } else if (token == "\\font_sf_scale") {
807 lex >> fonts_sans_scale[0];
808 lex >> fonts_sans_scale[1];
809 } else if (token == "\\font_tt_scale") {
810 lex >> fonts_typewriter_scale[0];
811 lex >> fonts_typewriter_scale[1];
812 } else if (token == "\\font_cjk") {
814 } else if (token == "\\use_microtype") {
815 lex >> use_microtype;
816 } else if (token == "\\paragraph_separation") {
819 paragraph_separation = parseptranslator().find(parsep);
820 } else if (token == "\\paragraph_indentation") {
822 string indentation = lex.getString();
823 pimpl_->indentation = HSpace(indentation);
824 } else if (token == "\\defskip") {
826 string const defskip = lex.getString();
827 pimpl_->defskip = VSpace(defskip);
828 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
830 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
831 } else if (token == "\\quotes_language") {
834 quotes_language = quoteslangtranslator().find(quotes_lang);
835 } else if (token == "\\papersize") {
838 papersize = papersizetranslator().find(ppsize);
839 } else if (token == "\\use_geometry") {
841 } else if (token == "\\use_package") {
846 use_package(package, packagetranslator().find(use));
847 } else if (token == "\\cite_engine") {
849 vector<string> engine = getVectorFromString(lex.getString());
850 setCiteEngine(engine);
851 } else if (token == "\\cite_engine_type") {
854 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
855 } else if (token == "\\biblio_style") {
857 biblio_style = lex.getString();
858 } else if (token == "\\use_bibtopic") {
860 } else if (token == "\\use_indices") {
862 } else if (token == "\\tracking_changes") {
863 lex >> track_changes;
864 } else if (token == "\\output_changes") {
865 lex >> output_changes;
866 } else if (token == "\\branch") {
868 docstring branch = lex.getDocString();
869 branchlist().add(branch);
872 string const tok = lex.getString();
873 if (tok == "\\end_branch")
875 Branch * branch_ptr = branchlist().find(branch);
876 if (tok == "\\selected") {
879 branch_ptr->setSelected(lex.getInteger());
881 if (tok == "\\filename_suffix") {
884 branch_ptr->setFileNameSuffix(lex.getInteger());
886 if (tok == "\\color") {
888 string color = lex.getString();
890 branch_ptr->setColor(color);
891 // Update also the Color table:
893 color = lcolor.getX11Name(Color_background);
895 lcolor.setColor(to_utf8(branch), color);
898 } else if (token == "\\index") {
900 docstring index = lex.getDocString();
902 indiceslist().add(index);
905 string const tok = lex.getString();
906 if (tok == "\\end_index")
908 Index * index_ptr = indiceslist().find(index);
909 if (tok == "\\shortcut") {
911 shortcut = lex.getDocString();
913 index_ptr->setShortcut(shortcut);
915 if (tok == "\\color") {
917 string color = lex.getString();
919 index_ptr->setColor(color);
920 // Update also the Color table:
922 color = lcolor.getX11Name(Color_background);
924 if (!shortcut.empty())
925 lcolor.setColor(to_utf8(shortcut), color);
928 } else if (token == "\\author") {
930 istringstream ss(lex.getString());
934 } else if (token == "\\paperorientation") {
937 orientation = paperorientationtranslator().find(orient);
938 } else if (token == "\\backgroundcolor") {
940 backgroundcolor = lyx::rgbFromHexName(lex.getString());
941 isbackgroundcolor = true;
942 } else if (token == "\\fontcolor") {
944 fontcolor = lyx::rgbFromHexName(lex.getString());
946 } else if (token == "\\notefontcolor") {
948 string color = lex.getString();
949 notefontcolor = lyx::rgbFromHexName(color);
950 lcolor.setColor("notefontcolor", color);
951 } else if (token == "\\boxbgcolor") {
953 string color = lex.getString();
954 boxbgcolor = lyx::rgbFromHexName(color);
955 lcolor.setColor("boxbgcolor", color);
956 } else if (token == "\\paperwidth") {
958 } else if (token == "\\paperheight") {
960 } else if (token == "\\leftmargin") {
962 } else if (token == "\\topmargin") {
964 } else if (token == "\\rightmargin") {
966 } else if (token == "\\bottommargin") {
968 } else if (token == "\\headheight") {
970 } else if (token == "\\headsep") {
972 } else if (token == "\\footskip") {
974 } else if (token == "\\columnsep") {
976 } else if (token == "\\paperfontsize") {
978 } else if (token == "\\papercolumns") {
980 } else if (token == "\\listings_params") {
983 listings_params = InsetListingsParams(par).params();
984 } else if (token == "\\papersides") {
987 sides = sidestranslator().find(psides);
988 } else if (token == "\\paperpagestyle") {
990 } else if (token == "\\bullet") {
992 } else if (token == "\\bulletLaTeX") {
993 readBulletsLaTeX(lex);
994 } else if (token == "\\secnumdepth") {
996 } else if (token == "\\tocdepth") {
998 } else if (token == "\\spacing") {
1002 if (nspacing == "other") {
1005 spacing().set(spacetranslator().find(nspacing), tmp_val);
1006 } else if (token == "\\float_placement") {
1007 lex >> float_placement;
1009 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
1010 string toktmp = pdfoptions().readToken(lex, token);
1011 if (!toktmp.empty()) {
1012 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
1016 } else if (token == "\\html_math_output") {
1019 html_math_output = static_cast<MathOutput>(temp);
1020 } else if (token == "\\html_be_strict") {
1021 lex >> html_be_strict;
1022 } else if (token == "\\html_css_as_file") {
1023 lex >> html_css_as_file;
1024 } else if (token == "\\html_math_img_scale") {
1025 lex >> html_math_img_scale;
1026 } else if (token == "\\html_latex_start") {
1028 html_latex_start = lex.getString();
1029 } else if (token == "\\html_latex_end") {
1031 html_latex_end = lex.getString();
1032 } else if (token == "\\output_sync") {
1034 } else if (token == "\\output_sync_macro") {
1035 lex >> output_sync_macro;
1036 } else if (token == "\\use_refstyle") {
1037 lex >> use_refstyle;
1039 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1049 // Quote argument if it contains spaces
1050 string quoteIfNeeded(string const & str) {
1051 if (contains(str, ' '))
1052 return "\"" + str + "\"";
1058 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1060 // The top of the file is written by the buffer.
1061 // Prints out the buffer info into the .lyx file given by file
1063 os << "\\save_transient_properties "
1064 << convert<string>(save_transient_properties) << '\n';
1066 // the document directory (must end with a path separator)
1067 // realPath() is used to resolve symlinks, while addPath(..., "")
1068 // ensures a trailing path separator.
1070 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1071 string const sysdir = inSystemDir(FileName(filepath), docsys) ? docsys
1072 : addPath(package().system_support().realPath(), "");
1073 string const relpath =
1074 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1075 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1076 filepath = addPath("/systemlyxdir", relpath);
1077 else if (!save_transient_properties || !lyxrc.save_origin)
1078 filepath = "unavailable";
1079 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1082 os << "\\textclass "
1083 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1084 baseClass()->name()), "layout"))
1087 // then the preamble
1088 if (!preamble.empty()) {
1089 // remove '\n' from the end of preamble
1090 docstring const tmppreamble = rtrim(preamble, "\n");
1091 os << "\\begin_preamble\n"
1092 << to_utf8(tmppreamble)
1093 << "\n\\end_preamble\n";
1097 if (!options.empty()) {
1098 os << "\\options " << options << '\n';
1101 // use the class options defined in the layout?
1102 os << "\\use_default_options "
1103 << convert<string>(use_default_options) << "\n";
1105 // the master document
1106 if (!master.empty()) {
1107 os << "\\master " << master << '\n';
1111 if (!removed_modules_.empty()) {
1112 os << "\\begin_removed_modules" << '\n';
1113 list<string>::const_iterator it = removed_modules_.begin();
1114 list<string>::const_iterator en = removed_modules_.end();
1115 for (; it != en; ++it)
1117 os << "\\end_removed_modules" << '\n';
1121 if (!layout_modules_.empty()) {
1122 os << "\\begin_modules" << '\n';
1123 LayoutModuleList::const_iterator it = layout_modules_.begin();
1124 LayoutModuleList::const_iterator en = layout_modules_.end();
1125 for (; it != en; ++it)
1127 os << "\\end_modules" << '\n';
1131 if (!included_children_.empty()) {
1132 os << "\\begin_includeonly" << '\n';
1133 list<string>::const_iterator it = included_children_.begin();
1134 list<string>::const_iterator en = included_children_.end();
1135 for (; it != en; ++it)
1137 os << "\\end_includeonly" << '\n';
1139 os << "\\maintain_unincluded_children "
1140 << convert<string>(maintain_unincluded_children) << '\n';
1142 // local layout information
1143 docstring const local_layout = getLocalLayout(false);
1144 if (!local_layout.empty()) {
1145 // remove '\n' from the end
1146 docstring const tmplocal = rtrim(local_layout, "\n");
1147 os << "\\begin_local_layout\n"
1148 << to_utf8(tmplocal)
1149 << "\n\\end_local_layout\n";
1151 docstring const forced_local_layout = getLocalLayout(true);
1152 if (!forced_local_layout.empty()) {
1153 // remove '\n' from the end
1154 docstring const tmplocal = rtrim(forced_local_layout, "\n");
1155 os << "\\begin_forced_local_layout\n"
1156 << to_utf8(tmplocal)
1157 << "\n\\end_forced_local_layout\n";
1160 // then the text parameters
1161 if (language != ignore_language)
1162 os << "\\language " << language->lang() << '\n';
1163 os << "\\language_package " << lang_package
1164 << "\n\\inputencoding " << inputenc
1165 << "\n\\fontencoding " << fontenc
1166 << "\n\\font_roman \"" << fonts_roman[0]
1167 << "\" \"" << fonts_roman[1] << '"'
1168 << "\n\\font_sans \"" << fonts_sans[0]
1169 << "\" \"" << fonts_sans[1] << '"'
1170 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1171 << "\" \"" << fonts_typewriter[1] << '"'
1172 << "\n\\font_math \"" << fonts_math[0]
1173 << "\" \"" << fonts_math[1] << '"'
1174 << "\n\\font_default_family " << fonts_default_family
1175 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1176 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1177 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1178 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1179 << ' ' << fonts_sans_scale[1]
1180 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1181 << ' ' << fonts_typewriter_scale[1]
1183 if (!fonts_cjk.empty()) {
1184 os << "\\font_cjk " << fonts_cjk << '\n';
1186 os << "\\use_microtype " << convert<string>(use_microtype) << '\n';
1187 os << "\\graphics " << graphics_driver << '\n';
1188 os << "\\default_output_format " << default_output_format << '\n';
1189 os << "\\output_sync " << output_sync << '\n';
1190 if (!output_sync_macro.empty())
1191 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1192 os << "\\bibtex_command " << bibtex_command << '\n';
1193 os << "\\index_command " << index_command << '\n';
1195 if (!float_placement.empty()) {
1196 os << "\\float_placement " << float_placement << '\n';
1198 os << "\\paperfontsize " << fontsize << '\n';
1200 spacing().writeFile(os);
1201 pdfoptions().writeFile(os);
1203 os << "\\papersize " << string_papersize[papersize]
1204 << "\n\\use_geometry " << convert<string>(use_geometry);
1205 map<string, string> const & packages = auto_packages();
1206 for (map<string, string>::const_iterator it = packages.begin();
1207 it != packages.end(); ++it)
1208 os << "\n\\use_package " << it->first << ' '
1209 << use_package(it->first);
1211 os << "\n\\cite_engine ";
1213 if (!cite_engine_.empty()) {
1214 LayoutModuleList::const_iterator be = cite_engine_.begin();
1215 LayoutModuleList::const_iterator en = cite_engine_.end();
1216 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1225 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1226 << "\n\\biblio_style " << biblio_style
1227 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1228 << "\n\\use_indices " << convert<string>(use_indices)
1229 << "\n\\paperorientation " << string_orientation[orientation]
1230 << "\n\\suppress_date " << convert<string>(suppress_date)
1231 << "\n\\justification " << convert<string>(justification)
1232 << "\n\\use_refstyle " << use_refstyle
1234 if (isbackgroundcolor == true)
1235 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1236 if (isfontcolor == true)
1237 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1238 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1239 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1240 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1241 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1243 BranchList::const_iterator it = branchlist().begin();
1244 BranchList::const_iterator end = branchlist().end();
1245 for (; it != end; ++it) {
1246 os << "\\branch " << to_utf8(it->branch())
1247 << "\n\\selected " << it->isSelected()
1248 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1249 << "\n\\color " << lyx::X11hexname(it->color())
1254 IndicesList::const_iterator iit = indiceslist().begin();
1255 IndicesList::const_iterator iend = indiceslist().end();
1256 for (; iit != iend; ++iit) {
1257 os << "\\index " << to_utf8(iit->index())
1258 << "\n\\shortcut " << to_utf8(iit->shortcut())
1259 << "\n\\color " << lyx::X11hexname(iit->color())
1264 if (!paperwidth.empty())
1265 os << "\\paperwidth "
1266 << VSpace(paperwidth).asLyXCommand() << '\n';
1267 if (!paperheight.empty())
1268 os << "\\paperheight "
1269 << VSpace(paperheight).asLyXCommand() << '\n';
1270 if (!leftmargin.empty())
1271 os << "\\leftmargin "
1272 << VSpace(leftmargin).asLyXCommand() << '\n';
1273 if (!topmargin.empty())
1274 os << "\\topmargin "
1275 << VSpace(topmargin).asLyXCommand() << '\n';
1276 if (!rightmargin.empty())
1277 os << "\\rightmargin "
1278 << VSpace(rightmargin).asLyXCommand() << '\n';
1279 if (!bottommargin.empty())
1280 os << "\\bottommargin "
1281 << VSpace(bottommargin).asLyXCommand() << '\n';
1282 if (!headheight.empty())
1283 os << "\\headheight "
1284 << VSpace(headheight).asLyXCommand() << '\n';
1285 if (!headsep.empty())
1287 << VSpace(headsep).asLyXCommand() << '\n';
1288 if (!footskip.empty())
1290 << VSpace(footskip).asLyXCommand() << '\n';
1291 if (!columnsep.empty())
1292 os << "\\columnsep "
1293 << VSpace(columnsep).asLyXCommand() << '\n';
1294 os << "\\secnumdepth " << secnumdepth
1295 << "\n\\tocdepth " << tocdepth
1296 << "\n\\paragraph_separation "
1297 << string_paragraph_separation[paragraph_separation];
1298 if (!paragraph_separation)
1299 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1301 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1302 os << "\n\\quotes_language "
1303 << string_quotes_language[quotes_language]
1304 << "\n\\papercolumns " << columns
1305 << "\n\\papersides " << sides
1306 << "\n\\paperpagestyle " << pagestyle << '\n';
1307 if (!listings_params.empty())
1308 os << "\\listings_params \"" <<
1309 InsetListingsParams(listings_params).encodedString() << "\"\n";
1310 for (int i = 0; i < 4; ++i) {
1311 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1312 if (user_defined_bullet(i).getFont() != -1) {
1313 os << "\\bullet " << i << " "
1314 << user_defined_bullet(i).getFont() << " "
1315 << user_defined_bullet(i).getCharacter() << " "
1316 << user_defined_bullet(i).getSize() << "\n";
1320 os << "\\bulletLaTeX " << i << " \""
1321 << lyx::to_ascii(user_defined_bullet(i).getText())
1327 os << "\\tracking_changes "
1328 << (save_transient_properties ? convert<string>(track_changes) : "false")
1331 os << "\\output_changes "
1332 << (save_transient_properties ? convert<string>(output_changes) : "false")
1335 os << "\\html_math_output " << html_math_output << '\n'
1336 << "\\html_css_as_file " << html_css_as_file << '\n'
1337 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1339 if (html_math_img_scale != 1.0)
1340 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1341 if (!html_latex_start.empty())
1342 os << "\\html_latex_start " << html_latex_start << '\n';
1343 if (!html_latex_end.empty())
1344 os << "\\html_latex_end " << html_latex_end << '\n';
1346 os << pimpl_->authorlist;
1350 void BufferParams::validate(LaTeXFeatures & features) const
1352 features.require(documentClass().requires());
1354 if (columns > 1 && language->rightToLeft())
1355 features.require("rtloutputdblcol");
1357 if (output_changes) {
1358 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1359 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1360 LaTeXFeatures::isAvailable("xcolor");
1362 switch (features.runparams().flavor) {
1363 case OutputParams::LATEX:
1364 case OutputParams::DVILUATEX:
1366 features.require("ct-dvipost");
1367 features.require("dvipost");
1368 } else if (xcolorulem) {
1369 features.require("ct-xcolor-ulem");
1370 features.require("ulem");
1371 features.require("xcolor");
1373 features.require("ct-none");
1376 case OutputParams::LUATEX:
1377 case OutputParams::PDFLATEX:
1378 case OutputParams::XETEX:
1380 features.require("ct-xcolor-ulem");
1381 features.require("ulem");
1382 features.require("xcolor");
1383 // improves color handling in PDF output
1384 features.require("pdfcolmk");
1386 features.require("ct-none");
1394 // Floats with 'Here definitely' as default setting.
1395 if (float_placement.find('H') != string::npos)
1396 features.require("float");
1398 for (PackageMap::const_iterator it = use_packages.begin();
1399 it != use_packages.end(); ++it) {
1400 if (it->first == "amsmath") {
1401 // AMS Style is at document level
1402 if (it->second == package_on ||
1403 features.isProvided("amsmath"))
1404 features.require(it->first);
1405 } else if (it->second == package_on)
1406 features.require(it->first);
1409 // Document-level line spacing
1410 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1411 features.require("setspace");
1413 // the bullet shapes are buffer level not paragraph level
1414 // so they are tested here
1415 for (int i = 0; i < 4; ++i) {
1416 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1418 int const font = user_defined_bullet(i).getFont();
1420 int const c = user_defined_bullet(i).getCharacter();
1426 features.require("latexsym");
1428 } else if (font == 1) {
1429 features.require("amssymb");
1430 } else if (font >= 2 && font <= 5) {
1431 features.require("pifont");
1435 if (pdfoptions().use_hyperref) {
1436 features.require("hyperref");
1437 // due to interferences with babel and hyperref, the color package has to
1438 // be loaded after hyperref when hyperref is used with the colorlinks
1439 // option, see http://www.lyx.org/trac/ticket/5291
1440 if (pdfoptions().colorlinks)
1441 features.require("color");
1443 if (!listings_params.empty()) {
1444 // do not test validity because listings_params is
1445 // supposed to be valid
1447 InsetListingsParams(listings_params).separatedParams(true);
1448 // we can't support all packages, but we should load the color package
1449 if (par.find("\\color", 0) != string::npos)
1450 features.require("color");
1453 // some languages are only available via polyglossia
1454 if (features.hasPolyglossiaExclusiveLanguages())
1455 features.require("polyglossia");
1457 if (useNonTeXFonts && fontsMath() != "auto")
1458 features.require("unicode-math");
1461 features.require("microtype");
1463 if (!language->requires().empty())
1464 features.require(language->requires());
1468 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1469 FileName const & filepath) const
1471 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1472 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1473 // \RequirePackage to do so, rather than the normal \usepackage
1474 // Do not try to load any other package before the document class, unless you
1475 // have a thorough understanding of the LATEX internals and know exactly what you
1477 if (features.mustProvide("fix-cm"))
1478 os << "\\RequirePackage{fix-cm}\n";
1479 // Likewise for fixltx2e. If other packages conflict with this policy,
1480 // treat it as a package bug (and report it!)
1481 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1482 if (features.mustProvide("fixltx2e"))
1483 os << "\\RequirePackage{fixltx2e}\n";
1485 os << "\\documentclass";
1487 DocumentClass const & tclass = documentClass();
1489 ostringstream clsoptions; // the document class options.
1491 if (tokenPos(tclass.opt_fontsize(),
1492 '|', fontsize) >= 0) {
1493 // only write if existing in list (and not default)
1494 clsoptions << fontsize << "pt,";
1497 // all paper sizes except of A4, A5, B5 and the US sizes need the
1499 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1500 && papersize != PAPER_USLETTER
1501 && papersize != PAPER_USLEGAL
1502 && papersize != PAPER_USEXECUTIVE
1503 && papersize != PAPER_A4
1504 && papersize != PAPER_A5
1505 && papersize != PAPER_B5;
1507 if (!use_geometry) {
1508 switch (papersize) {
1510 clsoptions << "a4paper,";
1512 case PAPER_USLETTER:
1513 clsoptions << "letterpaper,";
1516 clsoptions << "a5paper,";
1519 clsoptions << "b5paper,";
1521 case PAPER_USEXECUTIVE:
1522 clsoptions << "executivepaper,";
1525 clsoptions << "legalpaper,";
1559 if (sides != tclass.sides()) {
1562 clsoptions << "oneside,";
1565 clsoptions << "twoside,";
1571 if (columns != tclass.columns()) {
1573 clsoptions << "twocolumn,";
1575 clsoptions << "onecolumn,";
1579 && orientation == ORIENTATION_LANDSCAPE)
1580 clsoptions << "landscape,";
1582 // language should be a parameter to \documentclass
1583 if (language->babel() == "hebrew"
1584 && default_language->babel() != "hebrew")
1585 // This seems necessary
1586 features.useLanguage(default_language);
1588 ostringstream language_options;
1589 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1590 bool const use_polyglossia = features.usePolyglossia();
1591 bool const global = lyxrc.language_global_options;
1592 if (use_babel || (use_polyglossia && global)) {
1593 language_options << features.getBabelLanguages();
1594 if (!language->babel().empty()) {
1595 if (!language_options.str().empty())
1596 language_options << ',';
1597 language_options << language->babel();
1599 if (global && !features.needBabelLangOptions()
1600 && !language_options.str().empty())
1601 clsoptions << language_options.str() << ',';
1604 // the predefined options from the layout
1605 if (use_default_options && !tclass.options().empty())
1606 clsoptions << tclass.options() << ',';
1608 // the user-defined options
1609 if (!options.empty()) {
1610 clsoptions << options << ',';
1613 string strOptions(clsoptions.str());
1614 if (!strOptions.empty()) {
1615 strOptions = rtrim(strOptions, ",");
1617 os << '[' << from_utf8(strOptions) << ']';
1620 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1621 // end of \documentclass defs
1623 // if we use fontspec or newtxmath, we have to load the AMS packages here
1624 string const ams = features.loadAMSPackages();
1625 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1626 bool const use_newtxmath =
1627 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1628 ot1, false, false) == "newtxmath";
1629 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1630 os << from_ascii(ams);
1632 if (useNonTeXFonts) {
1633 if (!features.isProvided("fontspec"))
1634 os << "\\usepackage{fontspec}\n";
1635 if (features.mustProvide("unicode-math")
1636 && features.isAvailable("unicode-math"))
1637 os << "\\usepackage{unicode-math}\n";
1640 // font selection must be done before loading fontenc.sty
1641 string const fonts = loadFonts(features);
1643 os << from_utf8(fonts);
1645 if (fonts_default_family != "default")
1646 os << "\\renewcommand{\\familydefault}{\\"
1647 << from_ascii(fonts_default_family) << "}\n";
1649 // set font encoding
1650 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1651 if (!useNonTeXFonts && !features.isProvided("fontenc")
1652 && font_encoding() != "default") {
1653 // get main font encodings
1654 vector<string> fontencs = font_encodings();
1655 // get font encodings of secondary languages
1656 features.getFontEncodings(fontencs);
1657 if (!fontencs.empty()) {
1658 os << "\\usepackage["
1659 << from_ascii(getStringFromVector(fontencs))
1664 // handle inputenc etc.
1665 writeEncodingPreamble(os, features);
1668 if (!features.runparams().includeall && !included_children_.empty()) {
1669 os << "\\includeonly{";
1670 list<string>::const_iterator it = included_children_.begin();
1671 list<string>::const_iterator en = included_children_.end();
1673 for (; it != en; ++it) {
1674 string incfile = *it;
1675 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1676 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1678 if (!features.runparams().nice)
1680 // \includeonly doesn't want an extension
1681 incfile = changeExtension(incfile, string());
1682 incfile = support::latex_path(incfile);
1683 if (!incfile.empty()) {
1686 os << from_utf8(incfile);
1693 if (!features.isProvided("geometry")
1694 && (use_geometry || nonstandard_papersize)) {
1695 odocstringstream ods;
1696 if (!getGraphicsDriver("geometry").empty())
1697 ods << getGraphicsDriver("geometry");
1698 if (orientation == ORIENTATION_LANDSCAPE)
1699 ods << ",landscape";
1700 switch (papersize) {
1702 if (!paperwidth.empty())
1703 ods << ",paperwidth="
1704 << from_ascii(paperwidth);
1705 if (!paperheight.empty())
1706 ods << ",paperheight="
1707 << from_ascii(paperheight);
1709 case PAPER_USLETTER:
1710 ods << ",letterpaper";
1713 ods << ",legalpaper";
1715 case PAPER_USEXECUTIVE:
1716 ods << ",executivepaper";
1805 docstring const g_options = trim(ods.str(), ",");
1806 os << "\\usepackage";
1807 if (!g_options.empty())
1808 os << '[' << g_options << ']';
1809 os << "{geometry}\n";
1810 // output this only if use_geometry is true
1812 os << "\\geometry{verbose";
1813 if (!topmargin.empty())
1814 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1815 if (!bottommargin.empty())
1816 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1817 if (!leftmargin.empty())
1818 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1819 if (!rightmargin.empty())
1820 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1821 if (!headheight.empty())
1822 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1823 if (!headsep.empty())
1824 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1825 if (!footskip.empty())
1826 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1827 if (!columnsep.empty())
1828 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1831 } else if (orientation == ORIENTATION_LANDSCAPE
1832 || papersize != PAPER_DEFAULT) {
1833 features.require("papersize");
1836 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1837 if (pagestyle == "fancy")
1838 os << "\\usepackage{fancyhdr}\n";
1839 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1842 // only output when the background color is not default
1843 if (isbackgroundcolor == true) {
1844 // only require color here, the background color will be defined
1845 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1847 features.require("color");
1848 features.require("pagecolor");
1851 // only output when the font color is not default
1852 if (isfontcolor == true) {
1853 // only require color here, the font color will be defined
1854 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1856 features.require("color");
1857 features.require("fontcolor");
1860 // Only if class has a ToC hierarchy
1861 if (tclass.hasTocLevels()) {
1862 if (secnumdepth != tclass.secnumdepth()) {
1863 os << "\\setcounter{secnumdepth}{"
1867 if (tocdepth != tclass.tocdepth()) {
1868 os << "\\setcounter{tocdepth}{"
1874 if (paragraph_separation) {
1875 // when skip separation
1876 switch (getDefSkip().kind()) {
1877 case VSpace::SMALLSKIP:
1878 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1880 case VSpace::MEDSKIP:
1881 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1883 case VSpace::BIGSKIP:
1884 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1886 case VSpace::LENGTH:
1887 os << "\\setlength{\\parskip}{"
1888 << from_utf8(getDefSkip().length().asLatexString())
1891 default: // should never happen // Then delete it.
1892 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1895 os << "\\setlength{\\parindent}{0pt}\n";
1897 // when separation by indentation
1898 // only output something when a width is given
1899 if (getIndentation().asLyXCommand() != "default") {
1900 os << "\\setlength{\\parindent}{"
1901 << from_utf8(getIndentation().asLatexCommand())
1906 // Now insert the LyX specific LaTeX commands...
1907 features.resolveAlternatives();
1908 features.expandMultiples();
1911 if (!output_sync_macro.empty())
1912 os << from_utf8(output_sync_macro) +"\n";
1913 else if (features.runparams().flavor == OutputParams::LATEX)
1914 os << "\\usepackage[active]{srcltx}\n";
1915 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1916 os << "\\synctex=-1\n";
1919 // The package options (via \PassOptionsToPackage)
1920 os << from_ascii(features.getPackageOptions());
1922 // due to interferences with babel and hyperref, the color package has to
1923 // be loaded (when it is not already loaded) before babel when hyperref
1924 // is used with the colorlinks option, see
1925 // http://www.lyx.org/trac/ticket/5291
1926 // we decided therefore to load color always before babel, see
1927 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1928 os << from_ascii(features.getColorOptions());
1930 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1931 // we have to call babel before
1933 && (features.isRequired("jurabib")
1934 || features.isRequired("hyperref")
1935 || features.isRequired("varioref")
1936 || features.isRequired("vietnamese")
1937 || features.isRequired("japanese"))) {
1938 os << features.getBabelPresettings();
1940 os << from_utf8(babelCall(language_options.str(),
1941 features.needBabelLangOptions())) + '\n';
1942 os << features.getBabelPostsettings();
1945 // The optional packages;
1946 os << from_ascii(features.getPackages());
1948 // Additional Indices
1949 if (features.isRequired("splitidx")) {
1950 IndicesList::const_iterator iit = indiceslist().begin();
1951 IndicesList::const_iterator iend = indiceslist().end();
1952 for (; iit != iend; ++iit) {
1953 pair<docstring, docstring> indexname_latex =
1954 features.runparams().encoding->latexString(iit->index(),
1955 features.runparams().dryrun);
1956 if (!indexname_latex.second.empty()) {
1957 // issue a warning about omitted characters
1958 // FIXME: should be passed to the error dialog
1959 frontend::Alert::warning(_("Uncodable characters"),
1960 bformat(_("The following characters that are used in an index name are not\n"
1961 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1962 indexname_latex.second));
1964 os << "\\newindex[";
1965 os << indexname_latex.first;
1967 os << escape(iit->shortcut());
1973 os << from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1976 // * Hyperref manual: "Make sure it comes last of your loaded
1977 // packages, to give it a fighting chance of not being over-written,
1978 // since its job is to redefine many LaTeX commands."
1979 // * Email from Heiko Oberdiek: "It is usually better to load babel
1980 // before hyperref. Then hyperref has a chance to detect babel.
1981 // * Has to be loaded before the "LyX specific LaTeX commands" to
1982 // avoid errors with algorithm floats.
1983 // use hyperref explicitly if it is required
1984 if (features.isRequired("hyperref")) {
1985 OutputParams tmp_params = features.runparams();
1986 pdfoptions().writeLaTeX(tmp_params, os,
1987 features.isProvided("hyperref"));
1988 // correctly break URLs with hyperref and dvi output
1989 if (features.runparams().flavor == OutputParams::LATEX
1990 && features.isAvailable("breakurl"))
1991 os << "\\usepackage{breakurl}\n";
1992 } else if (features.isRequired("nameref"))
1993 // hyperref loads this automatically
1994 os << "\\usepackage{nameref}\n";
1996 // bibtopic needs to be loaded after hyperref.
1997 // the dot provides the aux file naming which LyX can detect.
1998 if (features.mustProvide("bibtopic"))
1999 os << "\\usepackage[dot]{bibtopic}\n";
2001 // Will be surrounded by \makeatletter and \makeatother when not empty
2002 otexstringstream atlyxpreamble;
2004 // Some macros LyX will need
2006 TexString tmppreamble = features.getMacros();
2007 if (!tmppreamble.str.empty())
2008 atlyxpreamble << "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2009 "LyX specific LaTeX commands.\n"
2010 << move(tmppreamble)
2013 // the text class specific preamble
2015 docstring tmppreamble = features.getTClassPreamble();
2016 if (!tmppreamble.empty())
2017 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2018 "Textclass specific LaTeX commands.\n"
2022 // suppress date if selected
2023 // use \@ifundefined because we cannot be sure that every document class
2024 // has a \date command
2026 atlyxpreamble << "\\@ifundefined{date}{}{\\date{}}\n";
2028 /* the user-defined preamble */
2029 if (!containsOnly(preamble, " \n\t")) {
2031 atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2032 "User specified LaTeX commands.\n";
2034 // Check if the user preamble contains uncodable glyphs
2035 odocstringstream user_preamble;
2036 docstring uncodable_glyphs;
2037 Encoding const * const enc = features.runparams().encoding;
2039 for (size_t n = 0; n < preamble.size(); ++n) {
2040 char_type c = preamble[n];
2041 if (!enc->encodable(c)) {
2042 docstring const glyph(1, c);
2043 LYXERR0("Uncodable character '"
2045 << "' in user preamble!");
2046 uncodable_glyphs += glyph;
2047 if (features.runparams().dryrun) {
2048 user_preamble << "<" << _("LyX Warning: ")
2049 << _("uncodable character") << " '";
2050 user_preamble.put(c);
2051 user_preamble << "'>";
2054 user_preamble.put(c);
2057 user_preamble << preamble;
2059 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2060 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2061 frontend::Alert::warning(
2062 _("Uncodable character in user preamble"),
2064 _("The user preamble of your document contains glyphs "
2065 "that are unknown in the current document encoding "
2066 "(namely %1$s).\nThese glyphs are omitted "
2067 " from the output, which may result in "
2068 "incomplete output."
2069 "\n\nPlease select an appropriate "
2070 "document encoding\n"
2071 "(such as utf8) or change the "
2072 "preamble code accordingly."),
2075 atlyxpreamble << user_preamble.str() << '\n';
2078 // footmisc must be loaded after setspace
2079 // Load it here to avoid clashes with footmisc loaded in the user
2080 // preamble. For that reason we also pass the options via
2081 // \PassOptionsToPackage in getPreamble() and not here.
2082 if (features.mustProvide("footmisc"))
2083 atlyxpreamble << "\\usepackage{footmisc}\n";
2085 // subfig loads internally the LaTeX package "caption". As
2086 // caption is a very popular package, users will load it in
2087 // the preamble. Therefore we must load subfig behind the
2088 // user-defined preamble and check if the caption package was
2089 // loaded or not. For the case that caption is loaded before
2090 // subfig, there is the subfig option "caption=false". This
2091 // option also works when a koma-script class is used and
2092 // koma's own caption commands are used instead of caption. We
2093 // use \PassOptionsToPackage here because the user could have
2094 // already loaded subfig in the preamble.
2095 if (features.mustProvide("subfig"))
2096 atlyxpreamble << "\\@ifundefined{showcaptionsetup}{}{%\n"
2097 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2098 "\\usepackage{subfig}\n";
2100 // Itemize bullet settings need to be last in case the user
2101 // defines their own bullets that use a package included
2102 // in the user-defined preamble -- ARRae
2103 // Actually it has to be done much later than that
2104 // since some packages like frenchb make modifications
2105 // at \begin{document} time -- JMarc
2106 docstring bullets_def;
2107 for (int i = 0; i < 4; ++i) {
2108 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2109 if (bullets_def.empty())
2110 bullets_def += "\\AtBeginDocument{\n";
2111 bullets_def += " \\def\\labelitemi";
2113 // `i' is one less than the item to modify
2120 bullets_def += "ii";
2126 bullets_def += '{' +
2127 user_defined_bullet(i).getText()
2132 if (!bullets_def.empty())
2133 atlyxpreamble << bullets_def << "}\n\n";
2135 if (!atlyxpreamble.empty())
2136 os << "\n\\makeatletter\n"
2137 << atlyxpreamble.release()
2138 << "\\makeatother\n\n";
2140 // We try to load babel late, in case it interferes with other packages.
2141 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2142 // called after babel, though.
2143 if (use_babel && !features.isRequired("jurabib")
2144 && !features.isRequired("hyperref")
2145 && !features.isRequired("varioref")
2146 && !features.isRequired("vietnamese")
2147 && !features.isRequired("japanese")) {
2148 os << features.getBabelPresettings();
2150 os << from_utf8(babelCall(language_options.str(),
2151 features.needBabelLangOptions())) + '\n';
2152 os << features.getBabelPostsettings();
2154 if (features.isRequired("bicaption"))
2155 os << "\\usepackage{bicaption}\n";
2156 if (!listings_params.empty() || features.mustProvide("listings"))
2157 os << "\\usepackage{listings}\n";
2158 if (!listings_params.empty()) {
2160 // do not test validity because listings_params is
2161 // supposed to be valid
2163 InsetListingsParams(listings_params).separatedParams(true);
2164 os << from_utf8(par);
2168 // xunicode needs to be loaded at least after amsmath, amssymb,
2169 // esint and the other packages that provide special glyphs
2170 // The package only supports XeTeX currently.
2171 if (features.runparams().flavor == OutputParams::XETEX
2173 os << "\\usepackage{xunicode}\n";
2175 // Polyglossia must be loaded last
2176 if (use_polyglossia) {
2178 os << "\\usepackage{polyglossia}\n";
2179 // set the main language
2180 os << "\\setdefaultlanguage";
2181 if (!language->polyglossiaOpts().empty())
2182 os << "[" << from_ascii(language->polyglossiaOpts()) << "]";
2183 os << "{" << from_ascii(language->polyglossia()) << "}\n";
2184 // now setup the other languages
2185 std::map<std::string, std::string> const polylangs =
2186 features.getPolyglossiaLanguages();
2187 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
2188 mit != polylangs.end() ; ++mit) {
2189 os << "\\setotherlanguage";
2190 if (!mit->second.empty())
2191 os << "[" << from_ascii(mit->second) << "]";
2192 os << "{" << from_ascii(mit->first) << "}\n";
2196 // Load custom language package here
2197 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2198 if (lang_package == "default")
2199 os << from_utf8(lyxrc.language_custom_package);
2201 os << from_utf8(lang_package);
2205 docstring const i18npreamble =
2206 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2207 if (!i18npreamble.empty())
2208 os << i18npreamble + '\n';
2214 void BufferParams::useClassDefaults()
2216 DocumentClass const & tclass = documentClass();
2218 sides = tclass.sides();
2219 columns = tclass.columns();
2220 pagestyle = tclass.pagestyle();
2221 use_default_options = true;
2222 // Only if class has a ToC hierarchy
2223 if (tclass.hasTocLevels()) {
2224 secnumdepth = tclass.secnumdepth();
2225 tocdepth = tclass.tocdepth();
2230 bool BufferParams::hasClassDefaults() const
2232 DocumentClass const & tclass = documentClass();
2234 return sides == tclass.sides()
2235 && columns == tclass.columns()
2236 && pagestyle == tclass.pagestyle()
2237 && use_default_options
2238 && secnumdepth == tclass.secnumdepth()
2239 && tocdepth == tclass.tocdepth();
2243 DocumentClass const & BufferParams::documentClass() const
2249 DocumentClassConstPtr BufferParams::documentClassPtr() const
2255 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2257 // evil, but this function is evil
2258 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2259 invalidateConverterCache();
2263 bool BufferParams::setBaseClass(string const & classname)
2265 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2266 LayoutFileList & bcl = LayoutFileList::get();
2267 if (!bcl.haveClass(classname)) {
2269 bformat(_("The layout file:\n"
2271 "could not be found. A default textclass with default\n"
2272 "layouts will be used. LyX will not be able to produce\n"
2274 from_utf8(classname));
2275 frontend::Alert::error(_("Document class not found"), s);
2276 bcl.addEmptyClass(classname);
2279 bool const success = bcl[classname].load();
2282 bformat(_("Due to some error in it, the layout file:\n"
2284 "could not be loaded. A default textclass with default\n"
2285 "layouts will be used. LyX will not be able to produce\n"
2287 from_utf8(classname));
2288 frontend::Alert::error(_("Could not load class"), s);
2289 bcl.addEmptyClass(classname);
2292 pimpl_->baseClass_ = classname;
2293 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2298 LayoutFile const * BufferParams::baseClass() const
2300 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2301 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2307 LayoutFileIndex const & BufferParams::baseClassID() const
2309 return pimpl_->baseClass_;
2313 void BufferParams::makeDocumentClass(bool const clone)
2318 invalidateConverterCache();
2319 LayoutModuleList mods;
2320 LayoutModuleList::iterator it = layout_modules_.begin();
2321 LayoutModuleList::iterator en = layout_modules_.end();
2322 for (; it != en; ++it)
2323 mods.push_back(*it);
2325 it = cite_engine_.begin();
2326 en = cite_engine_.end();
2327 for (; it != en; ++it)
2328 mods.push_back(*it);
2330 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2332 TextClass::ReturnValues success = TextClass::OK;
2333 if (!forced_local_layout_.empty())
2334 success = doc_class_->read(to_utf8(forced_local_layout_),
2336 if (!local_layout_.empty() &&
2337 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2338 success = doc_class_->read(to_utf8(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 docstring BufferParams::getLocalLayout(bool forced) const
2361 return from_utf8(doc_class_->forcedLayouts());
2363 return local_layout_;
2367 void BufferParams::setLocalLayout(docstring 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 return documentClass().outputFormat();
2394 bool BufferParams::isExportable(string const & format) const
2396 vector<string> backs = backends();
2397 for (vector<string>::const_iterator it = backs.begin();
2398 it != backs.end(); ++it)
2399 if (theConverters().isReachable(*it, format))
2405 FormatList const & BufferParams::exportableFormats(bool only_viewable) const
2407 FormatList & cached = only_viewable ?
2408 pimpl_->viewableFormatList : pimpl_->exportableFormatList;
2409 bool & valid = only_viewable ?
2410 pimpl_->isViewCacheValid : pimpl_->isExportCacheValid;
2414 vector<string> const backs = backends();
2415 set<string> excludes;
2416 if (useNonTeXFonts) {
2417 excludes.insert("latex");
2418 excludes.insert("pdflatex");
2421 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2422 for (vector<string>::const_iterator it = backs.begin() + 1;
2423 it != backs.end(); ++it) {
2424 FormatList r = theConverters().getReachable(*it, only_viewable,
2426 result.insert(result.end(), r.begin(), r.end());
2428 sort(result.begin(), result.end(), Format::formatSorter);
2435 bool BufferParams::isExportableFormat(string const & format) const
2437 FormatList const & formats = exportableFormats(true);
2438 FormatList::const_iterator fit = formats.begin();
2439 FormatList::const_iterator end = formats.end();
2440 for (; fit != end ; ++fit) {
2441 if ((*fit)->name() == format)
2448 vector<string> BufferParams::backends() const
2451 string const buffmt = bufferFormat();
2453 // FIXME: Don't hardcode format names here, but use a flag
2454 if (buffmt == "latex") {
2455 if (encoding().package() == Encoding::japanese)
2456 v.push_back("platex");
2458 if (!useNonTeXFonts) {
2459 v.push_back("pdflatex");
2460 v.push_back("latex");
2462 v.push_back("xetex");
2463 v.push_back("luatex");
2464 v.push_back("dviluatex");
2467 v.push_back(buffmt);
2469 v.push_back("xhtml");
2470 v.push_back("text");
2476 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2478 string const dformat = (format.empty() || format == "default") ?
2479 getDefaultOutputFormat() : format;
2480 DefaultFlavorCache::const_iterator it =
2481 default_flavors_.find(dformat);
2483 if (it != default_flavors_.end())
2486 OutputParams::FLAVOR result = OutputParams::LATEX;
2488 // FIXME It'd be better not to hardcode this, but to do
2489 // something with formats.
2490 if (dformat == "xhtml")
2491 result = OutputParams::HTML;
2492 else if (dformat == "text")
2493 result = OutputParams::TEXT;
2494 else if (dformat == "lyx")
2495 result = OutputParams::LYX;
2496 else if (dformat == "pdflatex")
2497 result = OutputParams::PDFLATEX;
2498 else if (dformat == "xetex")
2499 result = OutputParams::XETEX;
2500 else if (dformat == "luatex")
2501 result = OutputParams::LUATEX;
2502 else if (dformat == "dviluatex")
2503 result = OutputParams::DVILUATEX;
2505 // Try to determine flavor of default output format
2506 vector<string> backs = backends();
2507 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2508 // Get shortest path to format
2509 Graph::EdgePath path;
2510 for (vector<string>::const_iterator it = backs.begin();
2511 it != backs.end(); ++it) {
2512 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2513 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2518 result = theConverters().getFlavor(path);
2521 // cache this flavor
2522 default_flavors_[dformat] = result;
2527 string BufferParams::getDefaultOutputFormat() const
2529 if (!default_output_format.empty()
2530 && default_output_format != "default")
2531 return default_output_format;
2533 || encoding().package() == Encoding::japanese) {
2534 FormatList const & formats = exportableFormats(true);
2535 if (formats.empty())
2537 // return the first we find
2538 return formats.front()->name();
2541 return lyxrc.default_otf_view_format;
2542 return lyxrc.default_view_format;
2545 Font const BufferParams::getFont() const
2547 FontInfo f = documentClass().defaultfont();
2548 if (fonts_default_family == "rmdefault")
2549 f.setFamily(ROMAN_FAMILY);
2550 else if (fonts_default_family == "sfdefault")
2551 f.setFamily(SANS_FAMILY);
2552 else if (fonts_default_family == "ttdefault")
2553 f.setFamily(TYPEWRITER_FAMILY);
2554 return Font(f, language);
2558 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2560 return quoteslangtranslator().find(qs);
2564 bool BufferParams::isLatex() const
2566 return documentClass().outputType() == LATEX;
2570 bool BufferParams::isLiterate() const
2572 return documentClass().outputType() == LITERATE;
2576 bool BufferParams::isDocBook() const
2578 return documentClass().outputType() == DOCBOOK;
2582 void BufferParams::readPreamble(Lexer & lex)
2584 if (lex.getString() != "\\begin_preamble")
2585 lyxerr << "Error (BufferParams::readPreamble):"
2586 "consistency check failed." << endl;
2588 preamble = lex.getLongString(from_ascii("\\end_preamble"));
2592 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2594 string const expected = forced ? "\\begin_forced_local_layout" :
2595 "\\begin_local_layout";
2596 if (lex.getString() != expected)
2597 lyxerr << "Error (BufferParams::readLocalLayout):"
2598 "consistency check failed." << endl;
2601 forced_local_layout_ =
2602 lex.getLongString(from_ascii("\\end_forced_local_layout"));
2604 local_layout_ = lex.getLongString(from_ascii("\\end_local_layout"));
2608 bool BufferParams::setLanguage(string const & lang)
2610 Language const *new_language = languages.getLanguage(lang);
2611 if (!new_language) {
2612 // Language lang was not found
2615 language = new_language;
2620 void BufferParams::readLanguage(Lexer & lex)
2622 if (!lex.next()) return;
2624 string const tmptok = lex.getString();
2626 // check if tmptok is part of tex_babel in tex-defs.h
2627 if (!setLanguage(tmptok)) {
2628 // Language tmptok was not found
2629 language = default_language;
2630 lyxerr << "Warning: Setting language `"
2631 << tmptok << "' to `" << language->lang()
2637 void BufferParams::readGraphicsDriver(Lexer & lex)
2642 string const tmptok = lex.getString();
2643 // check if tmptok is part of tex_graphics in tex_defs.h
2646 string const test = tex_graphics[n++];
2648 if (test == tmptok) {
2649 graphics_driver = tmptok;
2654 "Warning: graphics driver `$$Token' not recognized!\n"
2655 " Setting graphics driver to `default'.\n");
2656 graphics_driver = "default";
2663 void BufferParams::readBullets(Lexer & lex)
2668 int const index = lex.getInteger();
2670 int temp_int = lex.getInteger();
2671 user_defined_bullet(index).setFont(temp_int);
2672 temp_bullet(index).setFont(temp_int);
2674 user_defined_bullet(index).setCharacter(temp_int);
2675 temp_bullet(index).setCharacter(temp_int);
2677 user_defined_bullet(index).setSize(temp_int);
2678 temp_bullet(index).setSize(temp_int);
2682 void BufferParams::readBulletsLaTeX(Lexer & lex)
2684 // The bullet class should be able to read this.
2687 int const index = lex.getInteger();
2689 docstring const temp_str = lex.getDocString();
2691 user_defined_bullet(index).setText(temp_str);
2692 temp_bullet(index).setText(temp_str);
2696 void BufferParams::readModules(Lexer & lex)
2698 if (!lex.eatLine()) {
2699 lyxerr << "Error (BufferParams::readModules):"
2700 "Unexpected end of input." << endl;
2704 string mod = lex.getString();
2705 if (mod == "\\end_modules")
2707 addLayoutModule(mod);
2713 void BufferParams::readRemovedModules(Lexer & lex)
2715 if (!lex.eatLine()) {
2716 lyxerr << "Error (BufferParams::readRemovedModules):"
2717 "Unexpected end of input." << endl;
2721 string mod = lex.getString();
2722 if (mod == "\\end_removed_modules")
2724 removed_modules_.push_back(mod);
2727 // now we want to remove any removed modules that were previously
2728 // added. normally, that will be because default modules were added in
2729 // setBaseClass(), which gets called when \textclass is read at the
2730 // start of the read.
2731 list<string>::const_iterator rit = removed_modules_.begin();
2732 list<string>::const_iterator const ren = removed_modules_.end();
2733 for (; rit != ren; ++rit) {
2734 LayoutModuleList::iterator const mit = layout_modules_.begin();
2735 LayoutModuleList::iterator const men = layout_modules_.end();
2736 LayoutModuleList::iterator found = find(mit, men, *rit);
2739 layout_modules_.erase(found);
2744 void BufferParams::readIncludeonly(Lexer & lex)
2746 if (!lex.eatLine()) {
2747 lyxerr << "Error (BufferParams::readIncludeonly):"
2748 "Unexpected end of input." << endl;
2752 string child = lex.getString();
2753 if (child == "\\end_includeonly")
2755 included_children_.push_back(child);
2761 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2763 switch (papersize) {
2765 // could be anything, so don't guess
2767 case PAPER_CUSTOM: {
2768 if (purpose == XDVI && !paperwidth.empty() &&
2769 !paperheight.empty()) {
2770 // heightxwidth<unit>
2771 string first = paperwidth;
2772 string second = paperheight;
2773 if (orientation == ORIENTATION_LANDSCAPE)
2776 return first.erase(first.length() - 2)
2782 // dvips and dvipdfm do not know this
2783 if (purpose == DVIPS || purpose == DVIPDFM)
2787 if (purpose == DVIPS || purpose == DVIPDFM)
2791 if (purpose == DVIPS || purpose == DVIPDFM)
2801 if (purpose == DVIPS || purpose == DVIPDFM)
2805 if (purpose == DVIPS || purpose == DVIPDFM)
2809 if (purpose == DVIPS || purpose == DVIPDFM)
2813 if (purpose == DVIPS || purpose == DVIPDFM)
2817 if (purpose == DVIPS || purpose == DVIPDFM)
2821 // dvipdfm does not know this
2822 if (purpose == DVIPDFM)
2826 if (purpose == DVIPDFM)
2830 if (purpose == DVIPS || purpose == DVIPDFM)
2834 if (purpose == DVIPS || purpose == DVIPDFM)
2838 if (purpose == DVIPS || purpose == DVIPDFM)
2842 if (purpose == DVIPS || purpose == DVIPDFM)
2846 if (purpose == DVIPS || purpose == DVIPDFM)
2850 if (purpose == DVIPS || purpose == DVIPDFM)
2854 if (purpose == DVIPS || purpose == DVIPDFM)
2858 if (purpose == DVIPS || purpose == DVIPDFM)
2862 if (purpose == DVIPS || purpose == DVIPDFM)
2866 if (purpose == DVIPS || purpose == DVIPDFM)
2870 if (purpose == DVIPS || purpose == DVIPDFM)
2874 if (purpose == DVIPS || purpose == DVIPDFM)
2878 if (purpose == DVIPS || purpose == DVIPDFM)
2882 if (purpose == DVIPS || purpose == DVIPDFM)
2886 if (purpose == DVIPS || purpose == DVIPDFM)
2889 case PAPER_USEXECUTIVE:
2890 // dvipdfm does not know this
2891 if (purpose == DVIPDFM)
2896 case PAPER_USLETTER:
2898 if (purpose == XDVI)
2905 string const BufferParams::dvips_options() const
2909 // If the class loads the geometry package, we do not know which
2910 // paper size is used, since we do not set it (bug 7013).
2911 // Therefore we must not specify any argument here.
2912 // dvips gets the correct paper size via DVI specials in this case
2913 // (if the class uses the geometry package correctly).
2914 if (documentClass().provides("geometry"))
2918 && papersize == PAPER_CUSTOM
2919 && !lyxrc.print_paper_dimension_flag.empty()
2920 && !paperwidth.empty()
2921 && !paperheight.empty()) {
2922 // using a custom papersize
2923 result = lyxrc.print_paper_dimension_flag;
2924 result += ' ' + paperwidth;
2925 result += ',' + paperheight;
2927 string const paper_option = paperSizeName(DVIPS);
2928 if (!paper_option.empty() && (paper_option != "letter" ||
2929 orientation != ORIENTATION_LANDSCAPE)) {
2930 // dvips won't accept -t letter -t landscape.
2931 // In all other cases, include the paper size
2933 result = lyxrc.print_paper_flag;
2934 result += ' ' + paper_option;
2937 if (orientation == ORIENTATION_LANDSCAPE &&
2938 papersize != PAPER_CUSTOM)
2939 result += ' ' + lyxrc.print_landscape_flag;
2944 string const BufferParams::font_encoding() const
2946 return font_encodings().empty() ? "default" : font_encodings().back();
2950 vector<string> const BufferParams::font_encodings() const
2952 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2954 vector<string> fontencs;
2956 // "default" means "no explicit font encoding"
2957 if (doc_fontenc != "default") {
2958 fontencs = getVectorFromString(doc_fontenc);
2959 if (!language->fontenc().empty()
2960 && ascii_lowercase(language->fontenc()) != "none") {
2961 vector<string> fencs = getVectorFromString(language->fontenc());
2962 vector<string>::const_iterator fit = fencs.begin();
2963 for (; fit != fencs.end(); ++fit) {
2964 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2965 fontencs.push_back(*fit);
2974 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2976 // suppress the babel call if there is no BabelName defined
2977 // for the document language in the lib/languages file and if no
2978 // other languages are used (lang_opts is then empty)
2979 if (lang_opts.empty())
2981 // either a specific language (AsBabelOptions setting in
2982 // lib/languages) or the prefs require the languages to
2983 // be submitted to babel itself (not the class).
2985 return "\\usepackage[" + lang_opts + "]{babel}";
2986 return "\\usepackage{babel}";
2990 docstring BufferParams::getGraphicsDriver(string const & package) const
2994 if (package == "geometry") {
2995 if (graphics_driver == "dvips"
2996 || graphics_driver == "dvipdfm"
2997 || graphics_driver == "pdftex"
2998 || graphics_driver == "vtex")
2999 result = from_ascii(graphics_driver);
3000 else if (graphics_driver == "dvipdfmx")
3001 result = from_ascii("dvipdfm");
3008 void BufferParams::writeEncodingPreamble(otexstream & os,
3009 LaTeXFeatures & features) const
3011 // XeTeX/LuaTeX: (see also #9740)
3012 // With Unicode fonts we use utf8-plain without encoding package.
3013 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
3014 // XeTeX must use ASCII encoding (see Buffer.cpp),
3015 // for LuaTeX, we load "luainputenc" (see below).
3016 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
3019 if (inputenc == "auto") {
3020 string const doc_encoding =
3021 language->encoding()->latexName();
3022 Encoding::Package const package =
3023 language->encoding()->package();
3025 // Create list of inputenc options:
3026 set<string> encodings;
3027 // luainputenc fails with more than one encoding
3028 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
3029 // list all input encodings used in the document
3030 encodings = features.getEncodingSet(doc_encoding);
3032 // If the "japanese" package (i.e. pLaTeX) is used,
3033 // inputenc must be omitted.
3034 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
3035 if ((!encodings.empty() || package == Encoding::inputenc)
3036 && !features.isRequired("japanese")
3037 && !features.isProvided("inputenc")) {
3038 os << "\\usepackage[";
3039 set<string>::const_iterator it = encodings.begin();
3040 set<string>::const_iterator const end = encodings.end();
3042 os << from_ascii(*it);
3045 for (; it != end; ++it)
3046 os << ',' << from_ascii(*it);
3047 if (package == Encoding::inputenc) {
3048 if (!encodings.empty())
3050 os << from_ascii(doc_encoding);
3052 if (features.runparams().flavor == OutputParams::LUATEX
3053 || features.runparams().flavor == OutputParams::DVILUATEX)
3054 os << "]{luainputenc}\n";
3056 os << "]{inputenc}\n";
3058 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3059 if (language->encoding()->name() == "utf8-cjk"
3060 && LaTeXFeatures::isAvailable("CJKutf8"))
3061 os << "\\usepackage{CJKutf8}\n";
3063 os << "\\usepackage{CJK}\n";
3065 } else if (inputenc != "default") {
3066 switch (encoding().package()) {
3067 case Encoding::none:
3068 case Encoding::japanese:
3070 case Encoding::inputenc:
3071 // do not load inputenc if japanese is used
3072 // or if the class provides inputenc
3073 if (features.isRequired("japanese")
3074 || features.isProvided("inputenc"))
3076 os << "\\usepackage[" << from_ascii(encoding().latexName());
3077 if (features.runparams().flavor == OutputParams::LUATEX
3078 || features.runparams().flavor == OutputParams::DVILUATEX)
3079 os << "]{luainputenc}\n";
3081 os << "]{inputenc}\n";
3084 if (encoding().name() == "utf8-cjk"
3085 && LaTeXFeatures::isAvailable("CJKutf8"))
3086 os << "\\usepackage{CJKutf8}\n";
3088 os << "\\usepackage{CJK}\n";
3091 // Load the CJK package if needed by a secondary language.
3092 // If the main encoding is some variant of UTF8, use CJKutf8.
3093 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3094 if (encoding().iconvName() == "UTF-8"
3095 && LaTeXFeatures::isAvailable("CJKutf8"))
3096 os << "\\usepackage{CJKutf8}\n";
3098 os << "\\usepackage{CJK}\n";
3104 string const BufferParams::parseFontName(string const & name) const
3106 string mangled = name;
3107 size_t const idx = mangled.find('[');
3108 if (idx == string::npos || idx == 0)
3111 return mangled.substr(0, idx - 1);
3115 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3117 if (fontsRoman() == "default" && fontsSans() == "default"
3118 && fontsTypewriter() == "default"
3119 && (fontsMath() == "default" || fontsMath() == "auto"))
3125 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3126 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3127 * Mapping=tex-text option assures TeX ligatures (such as "--")
3128 * are resolved. Note that tt does not use these ligatures.
3130 * -- add more GUI options?
3131 * -- add more fonts (fonts for other scripts)
3132 * -- if there's a way to find out if a font really supports
3133 * OldStyle, enable/disable the widget accordingly.
3135 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3136 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3137 // However, until v.2 (2010/07/11) fontspec only knew
3138 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3139 // was introduced for both XeTeX and LuaTeX (LuaTeX
3140 // didn't understand "Mapping=tex-text", while XeTeX
3141 // understood both. With most recent versions, both
3142 // variants are understood by both engines. However,
3143 // we want to provide support for at least TeXLive 2009
3144 // (for XeTeX; LuaTeX is only supported as of v.2)
3145 string const texmapping =
3146 (features.runparams().flavor == OutputParams::XETEX) ?
3147 "Mapping=tex-text" : "Ligatures=TeX";
3148 if (fontsRoman() != "default") {
3149 os << "\\setmainfont[" << texmapping;
3150 if (fonts_old_figures)
3151 os << ",Numbers=OldStyle";
3152 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3154 if (fontsSans() != "default") {
3155 string const sans = parseFontName(fontsSans());
3156 if (fontsSansScale() != 100)
3157 os << "\\setsansfont[Scale="
3158 << float(fontsSansScale()) / 100
3159 << "," << texmapping << "]{"
3162 os << "\\setsansfont[" << texmapping << "]{"
3165 if (fontsTypewriter() != "default") {
3166 string const mono = parseFontName(fontsTypewriter());
3167 if (fontsTypewriterScale() != 100)
3168 os << "\\setmonofont[Scale="
3169 << float(fontsTypewriterScale()) / 100
3173 os << "\\setmonofont{"
3180 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3181 bool const dryrun = features.runparams().dryrun;
3182 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3183 bool const nomath = (fontsMath() == "default");
3186 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3187 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3191 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3192 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3193 nomath, fontsSansScale());
3195 // MONOSPACED/TYPEWRITER
3196 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3197 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3198 nomath, fontsTypewriterScale());
3201 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3202 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3209 Encoding const & BufferParams::encoding() const
3211 // Main encoding for LaTeX output.
3213 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3214 // As the "flavor" is only known once export started, this
3215 // cannot be handled here. Instead, runparams.encoding is set
3216 // to ASCII in Buffer::makeLaTeXFile (for export)
3217 // and Buffer::writeLaTeXSource (for preview).
3219 return *(encodings.fromLyXName("utf8-plain"));
3220 if (inputenc == "auto" || inputenc == "default")
3221 return *language->encoding();
3222 Encoding const * const enc = encodings.fromLyXName(inputenc);
3225 LYXERR0("Unknown inputenc value `" << inputenc
3226 << "'. Using `auto' instead.");
3227 return *language->encoding();
3231 bool BufferParams::addCiteEngine(string const & engine)
3233 LayoutModuleList::const_iterator it = cite_engine_.begin();
3234 LayoutModuleList::const_iterator en = cite_engine_.end();
3235 for (; it != en; ++it)
3238 cite_engine_.push_back(engine);
3243 bool BufferParams::addCiteEngine(vector<string> const & engine)
3245 vector<string>::const_iterator it = engine.begin();
3246 vector<string>::const_iterator en = engine.end();
3248 for (; it != en; ++it)
3249 if (!addCiteEngine(*it))
3255 string const & BufferParams::defaultBiblioStyle() const
3257 return documentClass().defaultBiblioStyle();
3261 bool const & BufferParams::fullAuthorList() const
3263 return documentClass().fullAuthorList();
3267 void BufferParams::setCiteEngine(string const & engine)
3270 addCiteEngine(engine);
3274 void BufferParams::setCiteEngine(vector<string> const & engine)
3277 addCiteEngine(engine);
3281 vector<string> BufferParams::citeCommands() const
3283 static CitationStyle const default_style;
3284 vector<string> commands =
3285 documentClass().citeCommands(citeEngineType());
3286 if (commands.empty())
3287 commands.push_back(default_style.cmd);
3292 vector<CitationStyle> BufferParams::citeStyles() const
3294 static CitationStyle const default_style;
3295 vector<CitationStyle> styles =
3296 documentClass().citeStyles(citeEngineType());
3298 styles.push_back(default_style);
3302 void BufferParams::invalidateConverterCache() const
3304 pimpl_->isExportCacheValid = false;
3305 pimpl_->isViewCacheValid = false;